fork test

Dependencies:   BLE_API WIFI_API_32kRAM mbed nRF51822

Fork of NNN40_CLI by Delta

CLI_Source/ble_cli.cpp

Committer:
gillwei7
Date:
2015-09-11
Revision:
0:5c195ab2f696
Child:
3:38ec8ad317f4

File content as of revision 0:5c195ab2f696:

/**
 * File: ble-cli.c
 * Description: BLE CLI commands used by all applications BLE of profile.
 *
 * Copyright 2014 by CYNTEC Corporation.  All rights reserved.
 */
 
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include "command-interpreter.h"
#include "simple_uart.h"
#include "mbed.h"
#include "BLE.h"
#include "Gap.h"
#include "nrf_gpio.h"
#include "nrf_soc.h"
#include "ble_cli.h"
#include "ble_hci.h"
#include "app_error.h"
#include "PinNames.h"
//#include "custom_helper.h"
extern "C" {
	#include "ble_advdata.h"
}

#define S110_BLE_PERIPHERAL

#define APP_ADV_INTERVAL           64                     /**< The advertising interval (in units of 0.625 ms. This value corresponds to 40 ms). */
#define APP_ADV_TIMEOUT_IN_SECONDS 180                    /**< The advertising timeout (in units of seconds). */
#define APP_ADV_INTERVAL_MAX       16384 									// correspond to 10.24s
#define APP_ADV_INTERVAL_MIN       32		 									// correspond to 20ms
// Offset for Advertising Data.
#define APP_ADV_DATA_OFFSET 2

#define MAX_DEVNAME_LEN 32
#define CLI_SERVICE_MAX_NUM 10
#define CLI_CHAR_MAX_NUM 10
#define MAX_VALUE_LENGTH 20

#define CLI_CHAR_MODE_NONE 0
#define CLI_CHAR_MODE_READ 1
#define CLI_CHAR_MODE_WRITE 2
#define CLI_CHAR_MODE_INDICATE 3
#define CLI_CHAR_MODE_NOTIFY 4

#define CLI_FWVERION "DELTA_CLI_V1.6"
#define MODULE_NAME "DFCM-NNN40-DT1R"
#define ADVERTISING_LED_PIN_NO LED1
#define DELTA_DEBUG	1
//#define LBS_UUID_BASE {0x23, 0xD1, 0xBC, 0xEA, 0x5F, 0x78, 0x23, 0x15, 0xDE, 0xEF, 0x12, 0x12, 0x00, 0x00, 0x00, 0x00}
#define NEW_VS_SERVICE 0x0001


static ble_gap_addr_t m_peer_addr;
extern Serial console;
BLE deltaBLE; //gill 0904
extern const char* cyntecCommandErrorNames[];
extern void disconnectionCallback(Gap::Handle_t handle, Gap::DisconnectionReason_t reason);
// gill 0904
static bool connState = false;

typedef struct bufferGattChar {
//	bool flag;
	uint8_t mode;
	ble_uuid_t char_uuid;
	//uint8_t value[MAX_VALUE_LENGTH];
	uint16_t char_value_handle;
	uint8_t valueLength;
} bufferGattChar_t;

typedef struct bufferGattService {
//	uint16_t service_uuid_vs[8];
//	uint16_t service_uuid;
//	bool flag;
	ble_uuid_t service_uuid;
	bufferGattChar_t bufferGattChar[CLI_CHAR_MAX_NUM];
	uint16_t service_handle;
} bufferGattService_t;

/* save entry services */
bufferGattService_t bufferGattTest;
bufferGattService_t bufferService[CLI_SERVICE_MAX_NUM];


//static uint8_t debugMess[20]; // used in print debug
uint8_t service_count=0;
uint8_t char_count=0;
static uint16_t test_conn_handle; //Connection handle, assign after connected
extern bool advState; // currently no use

DigitalOut led1(p7);
DigitalOut led2(p13);

/******************************************************
 *               Function Definitions
 ******************************************************/

void onTimeoutCallback(Gap::TimeoutSource_t source)
{
	led1 = !led1;
}

void onConnectionCallback(const Gap::ConnectionCallbackParams_t *params)
{
    test_conn_handle = params->handle;
    //console.printf("connState:%d\r\n",connState);
    connState = true;
    led2 = !led2;
}

void disconnectionCallback(Gap::Handle_t handle, Gap::DisconnectionReason_t reason)
{
    //console.printf("connState:%d\r\n",connState);
    connState = false;
}


static void cyntecPrintOk(void)
{
	console.printf("\r\nOK\r\n\r\n");
}

static void cyntecPrintError(uint8_t errIdx)
{
	console.printf("\r\nERROR;");
	console.printf(cyntecCommandErrorNames[errIdx]);
	console.printf("\r\n\r\n");
}

#ifdef S120_BLE_CENTRAL
/**
 * @brief Scan parameters requested for scanning and connection.
 */
static const ble_gap_scan_params_t m_scan_param =
{
     0,                       // Active scanning set.
     0,                       // Selective scanning not set.
     NULL,                    // White-list not set.
     (uint16_t)SCAN_INTERVAL, // Scan interval.
     (uint16_t)SCAN_WINDOW,   // Scan window.
     0                        // Never stop scanning unless explicit asked to.
};
#endif

#ifdef S110_BLE_PERIPHERAL
/**@brief   Function for the Advertising functionality initialization.
 *
 * @details Encodes the required advertising data and passes it to the stack.
 *          Also builds a structure to be passed to the stack when starting advertising.
 */
static void advertising_init(void)
{
    uint32_t      err_code;
    ble_advdata_t advdata;
    ble_advdata_t scanrsp;
    //uint8_t       flags = BLE_GAP_ADV_FLAGS_LE_ONLY_LIMITED_DISC_MODE;
	
    ble_uuid_t adv_uuids[] = {{bufferService[0].service_uuid.uuid, 0x01}};

    memset(&advdata, 0, sizeof(advdata));
    advdata.name_type               = BLE_ADVDATA_FULL_NAME;
    advdata.include_appearance      = false;
    advdata.flags                   = BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE;
//    advdata.flags.size              = sizeof(flags);
//    advdata.flags.p_data            = &flags;

    memset(&scanrsp, 0, sizeof(scanrsp));
    scanrsp.uuids_complete.uuid_cnt = sizeof(adv_uuids) / sizeof(adv_uuids[0]);
    scanrsp.uuids_complete.p_uuids  = adv_uuids;
    
    err_code = ble_advdata_set(&advdata, &scanrsp);
    APP_ERROR_CHECK(err_code);
}


/**@brief Function for starting advertising.
 */
static uint8_t advertising_start(uint16_t advInterval, uint16_t advTimeout)
{
    uint32_t             err_code;
    ble_gap_adv_params_t adv_params;
    
    // Start advertising
    memset(&adv_params, 0, sizeof(adv_params));
    
    adv_params.type        = BLE_GAP_ADV_TYPE_ADV_IND; /**< Connectable undirected. */
    adv_params.p_peer_addr = NULL;
    adv_params.fp          = BLE_GAP_ADV_FP_ANY; /**< Allow scan requests and connect requests from any device. */
    adv_params.interval    = advInterval;
    adv_params.timeout     = advTimeout;

    err_code = sd_ble_gap_adv_start(&adv_params);
    //APP_ERROR_CHECK(err_code);
	  return err_code;
}



static void cynAdvertiseStartCommand(void)
{
	// adv start or adv stop or syntax error
	uint8_t argLen = 0;
	uint8_t *arg;
	/* arg0 is start or stop advertising */
	uint8_t *action = cyntecGetCommandArgument(0,&argLen);
	uint16_t advInterval;
	uint16_t advTimeout;
	
				switch (cyntecGetCommandTokenCnt())
				{
					case 2:
					advInterval = APP_ADV_INTERVAL;
					advTimeout = APP_ADV_TIMEOUT_IN_SECONDS;
					break;
					
					case 3:
					/* arg1 is adv interval parameter */
					arg = cyntecGetCommandArgument(1,&argLen);
					advInterval = cyntecAtoiUint16( arg, argLen );
					advTimeout = APP_ADV_TIMEOUT_IN_SECONDS;
					break;
					
					case 4:
					arg = cyntecGetCommandArgument(1,&argLen);
					advInterval = cyntecAtoiUint16( arg, argLen );
					arg = cyntecGetCommandArgument(2,&argLen);
					advTimeout = cyntecAtoiUint16( arg, argLen );
					break;
					
					default:
					advInterval = APP_ADV_INTERVAL;
					advTimeout = APP_ADV_TIMEOUT_IN_SECONDS;
					break;
				} 

				if ( advInterval< APP_ADV_INTERVAL_MIN | advInterval> APP_ADV_INTERVAL_MAX | advTimeout < 1| advTimeout > BLE_GAP_ADV_TIMEOUT_LIMITED_MAX )
					{
						cyntecPrintError(CYNTEC_CMD_ERR_ARGUMENT_OUT_OF_RANGE);
						return;
					}
//#ifdef DELTA_DEBUG			
//sprintf((char *)&debugMess[0],"[%d][%d]", advInterval,advTimeout);
//console.printf(debugMess);
//#endif
//				service_Test();
				advertising_init();
				uint8_t error_code = advertising_start(advInterval, advTimeout);
					
					if (error_code==NRF_SUCCESS)
					{
						cyntecPrintOk();
						nrf_gpio_pin_set(ADVERTISING_LED_PIN_NO); 
					}
					else if  (error_code==NRF_ERROR_INVALID_STATE)
					{
						cyntecPrintError(CYNTEC_CMD_ERR_INVALID_STATE_TO_PERFORM_OPERATION);
						return;
					}
					else
					{
						console.printf("ERROR;\r\n");
					}
}

/**@brief Function for stop advertising.
 */
static void cynAdvertiseStopCommand(void)
{
  uint8_t advStopErr = 0; 
	advStopErr = sd_ble_gap_adv_stop();
	if (advStopErr == NRF_SUCCESS)
	{
		cyntecPrintOk();
		nrf_gpio_pin_clear(ADVERTISING_LED_PIN_NO);
	}
	else if (advStopErr==NRF_ERROR_INVALID_STATE)
	{
						cyntecPrintError(CYNTEC_CMD_ERR_WRONG_NUMBER_OF_ARGUMENTS);
						return;
	}
	else{
		console.printf("ERROR;\r\n");
	}
}

//gill modify 20150904 for accept blank in name
static void cynBLENameCommand(void)
{
	if (cyntecGetCommandTokenCnt() >= 3)
	{
		uint8_t tempNameLen = 0;
		// check first and last char is "
		uint8_t *argName1 = cyntecGetCommandArgument(0, &tempNameLen);
		uint8_t *argNameLast = cyntecGetCommandArgument(cyntecGetCommandTokenCnt() - 3, &tempNameLen);
		char bracket = '*';
		//console.printf("%02X\r\n",tempNameLen);
		if (!memcmp(&argName1[0],&bracket,sizeof(char)) && !memcmp(&argNameLast[tempNameLen - 1],&bracket,sizeof(char)))
		//if (!memcmp(&argName1[0],&bracket,sizeof(char)))
		{
		uint8_t nameLen = 0;
		uint8_t *argName = cyntecGetCommandArgument(0, &nameLen);
		uint8_t * argName2 = cyntecGetCommandTotalBuffer();
		uint32_t err_code;
		ble_gap_conn_sec_mode_t sec_mode;
		//console.printf("%02X\r\n",cyntecGetTotalIndex());
		console.printf("\r\nSet BLE Name: ");	
		uint8_t i = 0;
		for(i = 0; i < cyntecGetTotalIndex()-12; i++) {  
			console.printf("%c",argName2[11+i]);
		}
		BLE_GAP_CONN_SEC_MODE_SET_OPEN(&sec_mode);
		err_code = sd_ble_gap_device_name_set(&sec_mode,
																					(const uint8_t *) &argName2[11],
																					(uint16_t) (cyntecGetTotalIndex()-12));
		if (err_code == NRF_SUCCESS) {
			cyntecPrintOk();
		}
		else {
			console.printf("ERROR;%04X\r\n",err_code);
		}																	
		APP_ERROR_CHECK(err_code);
		
		
//#ifdef DELTADEBUG																					
		//console.printf("\r\nSet BLE Name: ");																			
//		uint8_t i = 0;
//		for(i = 0; i < nameLen; i++)
//		{
//			console.printf("%c",argName[i]);
//		}

//#endif
		//console.printf("\r\nPrint buffer:\r\n");
		//console.printf("%s\r\n",cyntecGetCommandTotalBuffer());
		
		/* Re-init application setting */
		//cyntecCLIAppInit();
		}
		else
		{
			cyntecPrintError(CYNTEC_CMD_ERR_ARGUMENT_SYNTAX_ERROR);
		}
	} else if (cyntecGetCommandTokenCnt() == 2){
		uint8_t bleName[BLE_GAP_DEVNAME_MAX_LEN] = {"\0"};
		uint16_t bleLen = BLE_GAP_DEVNAME_MAX_LEN - APP_ADV_DATA_OFFSET;
		uint32_t err_code;
	
		err_code = sd_ble_gap_device_name_get(&bleName[APP_ADV_DATA_OFFSET], &bleLen);
		APP_ERROR_CHECK(err_code);
		
		console.printf("\r\nOK;");			
		console.printf("%s",bleName+APP_ADV_DATA_OFFSET);
		console.printf(";\r\n");
	}	
	else{
		cyntecPrintError(CYNTEC_CMD_ERR_WRONG_NUMBER_OF_ARGUMENTS);
		return;
	}		
}
#endif

static void cynBLEInfoCommand(void)
{
	console.printf("\r\nOK;F/W version:");
	console.printf(CLI_FWVERION);
	console.printf(";Module name:");
	console.printf(MODULE_NAME);
	console.printf("\r\n\r\n");
}

/**@brief Set the radio's transmit power.
 *
 * @param[in] tx_power Radio transmit power in dBm (accepted values are -40, -30, -20, -16, -12, -8, -4, 0, and 4 dBm).
 *
 * @note -40 dBm will not actually give -40 dBm, but will instead be remapped to -30 dBm.
 */
static void cynBLESetTxPowerCommand (void)
{
	if (cyntecGetCommandTokenCnt() == 3)
	{
		uint32_t err_code;
		uint8_t txLen=0;
		uint8_t *arg = cyntecGetCommandArgument(0,&txLen);
		
//		uint8_t *arg = cyntecGetMinusArgument(0,&txLen);
		
//		cyntecGetMinusArgument();
//		const char *value  = (const char *)arg;
//		sprintf((char *)&debugMess[0],"\r\n[%i]\r\n",*value);
//		console.printf(debugMess);
		const uint8_t NUM_TXPOW = 9;
		bool inputSwitch = false; // if find matched case in TxPow, assign true 
	
		int8_t validTxPow[NUM_TXPOW] = {-40, -30, -20, -16, -12, -8, -4, 0, 4};
		uint8_t i;
		int8_t setValue;
		
		if ( arg != NULL ) {
			setValue = atoi((const char *)arg);
//			sprintf((char *)&debugMess[0],"\r\n[%i]\r\n",setValue);
//			console.printf(debugMess);
			for (i = 0; i < NUM_TXPOW; i++)
			{
				if (setValue == validTxPow[i])
				{
					err_code = sd_ble_gap_tx_power_set(setValue);
					APP_ERROR_CHECK(err_code);
					inputSwitch = true;
					break;
				}
			}
			
			if ( inputSwitch )
				cyntecPrintOk();
			else
				console.printf("\r\nWrong Input; Accept Tx Pow: -40, -30, -20, -16, -12, -8, -4, 0, 4\r\n");
		}
		clearBuffer(); // clear the commandState.buffer
		return;
	}
	else{
		cyntecPrintError(CYNTEC_CMD_ERR_WRONG_NUMBER_OF_ARGUMENTS);
		return;
	}
}

static void cynBLEAddressCommand(void)
{
	if (cyntecGetCommandTokenCnt() == 3)
	{
		uint8_t argLen = 0;
		uint8_t *arg = cyntecGetCommandArgument(0, &argLen);
		uint32_t err_code;
		uint8_t addr,i;
		
		/* should with "0x" + 12 len addr */
		if (argLen == 14) {
			if (arg[0] != '0' || arg[1] != 'x') {
				cyntecPrintError(CYNTEC_CMD_ERR_ARGUMENT_SYNTAX_ERROR);
				return;				
			}
				
			m_peer_addr.addr_type = BLE_GAP_ADDR_TYPE_PUBLIC;

			for ( i = 1 ; i < 7 ; i++)
			{
				addr = cyntecArgToUint8(arg+2*i, 2);
				/* 5 - (i-1) */
				m_peer_addr.addr[6-i] = addr; 
			}					
			
			err_code = sd_ble_gap_address_set(BLE_GAP_ADDR_CYCLE_MODE_NONE, &m_peer_addr);
			APP_ERROR_CHECK(err_code);
			
		} else {  //argLen != 14
			cyntecPrintError(CYNTEC_CMD_ERR_ARGUMENT_SYNTAX_ERROR);
			return;
		}

//#ifdef DELTADEBUG
//		uint8_t buf2[20];
//		console.printf("\r\nSet BLE Address: ");
//		sprintf((char *)&buf2[0],(const char *)"[%02X %02X %02X %02X %02X %02X]", 
//						m_peer_addr.addr[0], m_peer_addr.addr[1], m_peer_addr.addr[2], 
//						m_peer_addr.addr[3], m_peer_addr.addr[4], m_peer_addr.addr[5]);			
//		console.printf(buf2);
//#endif		
		
		cyntecPrintOk();
	} else if (cyntecGetCommandTokenCnt() == 2){

		uint32_t err_code;
		err_code = sd_ble_gap_address_get(&m_peer_addr);
		APP_ERROR_CHECK(err_code);
		
		cyntecPrintOk();
				
		console.printf("[%02X %02X %02X %02X %02X %02X]", 
						m_peer_addr.addr[5], m_peer_addr.addr[4], m_peer_addr.addr[3], 
						m_peer_addr.addr[2], m_peer_addr.addr[1], m_peer_addr.addr[0]);
	}
	else { //cyntecGetCommandTokenCnt() not equal to 2 or 3
		cyntecPrintError(CYNTEC_CMD_ERR_WRONG_NUMBER_OF_ARGUMENTS);
	}
	return;
}

#ifdef S120_BLE_CENTRAL
/**@breif Function to start scanning.
 */
static void scan_start(void)
{
    uint32_t err_code = sd_ble_gap_scan_start(&m_scan_param);
    APP_ERROR_CHECK(err_code);
}

/**@breif Function to start scanning.
 */
static void scan_stop(void)
{
    uint32_t err_code = sd_ble_gap_scan_stop();
    APP_ERROR_CHECK(err_code);
}

static void cynBLEScanCommand(void)
{
	uint8_t *arg = cyntecGetCommandArgument(0,NULL);
	
	if ( arg != NULL ) {
		if ( arg[0] == '1' ) {
			console.printf("\r\nStart Scanning");
			scan_start();
		}
		else if ( arg[0] == '0' ) {
			console.printf("\r\nStop Scanning");
			scan_stop();
		}
		else
			console.printf("\r\nUsage: cynb scan <1|0>");
			console.printf("\r\n");
	}	
}

static void cynBLEConnectCommand(void)
{
	if (cyntecGetCommandTokenCnt() == 3)
	{	
		uint8_t devNameLen = 0;
		uint8_t *argDevName = cyntecGetCommandArgument(0, &devNameLen);
		
		if ( argDevName != NULL ) {
			uint8_t i;
			for (i = 0; i < devNameLen; i++) {
				targetDevName[i] = argDevName[i];
			}
			if (i < devNameLen)
				targetDevName[i] = '\0';
		}
		
		console.printf("\r\nSearch for device name:");
		console.printf(argDevName);
		
		scan_start();
	} else {
			console.printf("\r\nUsage: cynb connect <Device Name>");
			console.printf("\r\n(Ex:cynb connect CYN_DEVICE");		
	}
}
#endif

static void cynBLEDisconnectCommand(void)
{
	uint32_t err_code;
#ifdef S110_BLE_PERIPHERAL
	//marcus need to modify
	err_code = sd_ble_gap_disconnect(test_conn_handle, BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION);
#endif	
	
#ifdef S120_BLE_CENTRAL
	err_code = sd_ble_gap_connect_cancel();	// No function defined currently
#endif
	if (err_code == NRF_SUCCESS)
	{

		cyntecPrintOk();
//	APP_ERROR_CHECK(err_code);
	}
	else  if (err_code ==NRF_ERROR_INVALID_STATE){
		cyntecPrintError(CYNTEC_CMD_ERR_INVALID_STATE_TO_PERFORM_OPERATION);
	}
	else {
		console.printf("ERROR;\r\n");
	}
}

static uint8_t isValidGPIO(uint8_t num)
{
	uint8_t cfgPin[] = {0,1,2,3,4,5,6,7,13,16,17,23,24,25,29};
	uint8_t i;
	
	for ( i = 0; i < sizeof(cfgPin) ; i++ )
	{
			if ( num == cfgPin[i] )
				return 1;
	}
	
	return 0;
}

static void cynBLESystemOffCommand(void)
{
	if (cyntecGetCommandTokenCnt() == 3)
	{
		uint8_t argLen = 0;
		uint8_t *arg = cyntecGetCommandArgument(0,&argLen);
		uint8_t gpioNum = cyntecAtoi( arg, argLen );
		// Can only use 0,1,2,3,4,5,6,7,13,16,17,23,24,25,29
		if (!isValidGPIO(gpioNum))
		{
			cyntecPrintError(CYNTEC_CMD_ERR_ARGUMENT_OUT_OF_RANGE);
			return;
		}
		nrf_gpio_cfg_sense_input(gpioNum,
														 NRF_GPIO_PIN_PULLUP, 
														 NRF_GPIO_PIN_SENSE_LOW);	
		cyntecPrintOk();		
	} else if (cyntecGetCommandTokenCnt() == 2){
		/* default wake up pin is uart Rx pin */
		nrf_gpio_cfg_sense_input(RX_PIN_NUMBER,
														 NRF_GPIO_PIN_PULLUP, 
														 NRF_GPIO_PIN_SENSE_LOW);
		cyntecPrintOk();
	} else{
		cyntecPrintError(CYNTEC_CMD_ERR_WRONG_NUMBER_OF_ARGUMENTS);
	}
	sd_power_system_off();
}

static void cynBLEGPIOCommand(void)
{
	
	if (cyntecGetCommandTokenCnt() == 4)
	{
		uint8_t argLen = 0;
		uint8_t *arg = cyntecGetCommandArgument(0,&argLen);
		uint8_t gpioNum = cyntecAtoi( arg, argLen );
		
		if (!isValidGPIO(gpioNum))
		{
			cyntecPrintError(CYNTEC_CMD_ERR_ARGUMENT_OUT_OF_RANGE);
			return;
		}
		
		/* arg2 is set or clear */
		uint8_t *action = cyntecGetCommandArgument(1,&argLen);
		
		if ( cyntecStrCmp(action,(unsigned char *)"set",argLen) == 1 )
		{
			nrf_gpio_cfg_output(gpioNum);
			nrf_gpio_pin_set(gpioNum);
			cyntecPrintOk();
		} else if ( cyntecStrCmp(action,(unsigned char *)"clear",argLen) == 1 ) {
			nrf_gpio_cfg_output(gpioNum);
			nrf_gpio_pin_clear(gpioNum);
			cyntecPrintOk();
		} else {
			cyntecPrintError(CYNTEC_CMD_ERR_ARGUMENT_SYNTAX_ERROR);
		}
	} else {
			cyntecPrintError(CYNTEC_CMD_ERR_WRONG_NUMBER_OF_ARGUMENTS);
	}
}

static void cynResetCommand(void)
{
	cyntecPrintOk();
	// On assert, the system can only recover with a reset.
  NVIC_SystemReset();
}

// gill modify for update value in non-connect state 20150904
// Change set value connection handle 
static void cynBLEUpdateUUIDCommand(void)
{
	uint8_t i,j;
	uint8_t value[MAX_VALUE_LENGTH];
	memset(value, 0, sizeof(value));
//	uint8_t buf_char_uuid_type;
	ble_uuid_t buf_service_uuid;
	ble_uuid_t buf_char_uuid;
	uint8_t argLen = 0;
	uint8_t *arg;
	uint8_t valueLengthBuffer = 0;
	uint8_t modeType;
	bool updatematchFlag = false; // Check matched characteristic found
	uint16_t len = MAX_VALUE_LENGTH;
	uint32_t err_code;
	// check if argument count is right
	if (cyntecGetCommandTokenCnt() != 5)
	{
		cyntecPrintError(CYNTEC_CMD_ERR_WRONG_NUMBER_OF_ARGUMENTS);
		return;
	}
	else
	{
			arg = cyntecGetCommandArgument(0,&argLen);
			if (arg[0] != '0' | arg[1] != 'x' | argLen%2 != 0) {
				cyntecPrintError(CYNTEC_CMD_ERR_ARGUMENT_SYNTAX_ERROR);
				return;					 
			}
			else {
						// Handle input parameter - Service UUID
					arg = cyntecGetCommandArgument(0,&argLen);
					
					if (argLen == 6 && arg[0] == '0' && arg[1] == 'x')
					{
						buf_service_uuid.uuid = cyntecArgToUint16( (arg + 2), (argLen - 2));
						buf_service_uuid.type = BLE_UUID_TYPE_BLE;
					}
					if (argLen == 34 && arg[0] == '0' && arg[1] == 'x')
					{
						buf_service_uuid.uuid = cyntecArgToUint16( (arg + 6), 4);
						buf_service_uuid.type = BLE_UUID_TYPE_VENDOR_BEGIN;
					}
					
					// Handle input parameter -  Characteristic UUID
					argLen = 0;
					arg = cyntecGetCommandArgument(1,&argLen);
					
					if (argLen == 6 && arg[0] == '0' && arg[1] == 'x')
					{
						buf_char_uuid.uuid = cyntecArgToUint16( (arg + 2), (argLen - 2));
						buf_char_uuid.type = BLE_UUID_TYPE_BLE;
					}
					if (argLen == 34 && arg[0] == '0' && arg[1] == 'x')
					{
						buf_char_uuid.uuid = cyntecArgToUint16( (arg + 6), 4);
						buf_char_uuid.type = BLE_UUID_TYPE_VENDOR_BEGIN;
					}
//					sprintf((char *)&debugMess[0],"buf_service_uuid[%d,%4X]\r\n",buf_service_uuid.type,buf_service_uuid.uuid);
//					console.printf(debugMess);
					
					// Handle input parameter -  value
					arg = cyntecGetCommandArgument(2,&argLen);
					valueLengthBuffer = (argLen-2)/2;
				 for (i=0 ; i < (argLen-2)/2; i++)
					{
						value[i]  = cyntecArgToUint8(arg+2*(i+1), 2);
						// debug
		//							sprintf((char *)&buf[0],"[%2X]",value[i]);
		//							console.printf(buf);
					}
					
				}
					// debug message
//					sprintf((char *)&buf[0],"value:[%02X]", value);
//					console.printf(buf);
	
			for ( i = 0 ; i < CLI_SERVICE_MAX_NUM ; i++ )
				{
					if ( (bufferService[i].service_uuid.uuid == buf_service_uuid.uuid) &(bufferService[i].service_uuid.type == buf_service_uuid.type)& (updatematchFlag == false))
					{
							//readmatchFlag = true;
							for ( j = 0 ; j < CLI_CHAR_MAX_NUM ; j++ )
							{
								if ( (bufferService[i].bufferGattChar[j].char_uuid.uuid == buf_char_uuid.uuid) &(bufferService[i].bufferGattChar[j].char_uuid.type == buf_char_uuid.type)& (updatematchFlag == false))
								{
									modeType = bufferService[i].bufferGattChar[j].mode;
								//memset(bufferService[i].bufferGattChar[j].value, 0, sizeof(bufferService[i].bufferGattChar[j].value));								
								// Identify characteristic property is notify or indicate
								if (((modeType & (1 << CLI_CHAR_MODE_INDICATE)) | (modeType & (1 << CLI_CHAR_MODE_NOTIFY))) )
								{
										if (bufferService[i].bufferGattChar[j].mode & (1 << CLI_CHAR_MODE_INDICATE))
											modeType = BLE_GATT_HVX_INDICATION ;
										if (bufferService[i].bufferGattChar[j].mode & (1 << CLI_CHAR_MODE_NOTIFY))
											modeType = BLE_GATT_HVX_NOTIFICATION;
										ble_gatts_hvx_params_t hvx_params;
										memset(&hvx_params, 0, sizeof(hvx_params));
										hvx_params.handle   = bufferService[i].bufferGattChar[j].char_value_handle;
										hvx_params.type     = modeType;
										hvx_params.offset   = 0;
										hvx_params.p_len    = &len;
										hvx_params.p_data   = value;
										if (connState) // If connected, send notification/indication 
										{
											err_code = sd_ble_gatts_hvx(test_conn_handle, &hvx_params);
									
											if (err_code == NRF_SUCCESS)
											{
												//do nothing
											}
											else if ((err_code != NRF_SUCCESS) &&
											(err_code != NRF_ERROR_INVALID_STATE) &&
											(err_code != BLE_ERROR_NO_TX_BUFFERS) &&
											(err_code != BLE_ERROR_GATTS_SYS_ATTR_MISSING)
											)
											{
												console.printf("HVX ERROR;%04X\r\n",err_code);
											}
										}
										
								}
							
								// Update database
								bufferService[i].bufferGattChar[j].valueLength = valueLengthBuffer;
								ble_gatts_value_t bufGattsValue;
								memset(&bufGattsValue, 0, sizeof(bufGattsValue));
								bufGattsValue.len = len;
								bufGattsValue.offset = 0;
								bufGattsValue.p_value = value;
								//err_code = sd_ble_gatts_value_set(bufferService[i].bufferGattChar[j].char_value_handle, 
//												 0, 
//												 &len, 
//												 value);
								err_code = sd_ble_gatts_value_set(
								//test_conn_handle,
								BLE_CONN_HANDLE_INVALID, // User can update in non-connected state 
								bufferService[i].bufferGattChar[j].char_value_handle,
								&bufGattsValue
								);
								
								if (err_code == NRF_SUCCESS)
								{
									cyntecPrintOk();
								}
								else
								{
									console.printf("Set ERROR;%04X\r\n",err_code);
								}
								updatematchFlag = true;
								return;
							}
						}
					}	
			}
			if (updatematchFlag == false){
					cyntecPrintError(CYNTEC_CMD_ERR_NO_MATCHED_ARGUMENT);
			} 
		}
}

static void cynBLEReadDataCommand(void)
{ 
		
	if (cyntecGetCommandTokenCnt() != 4)
		{
			cyntecPrintError(CYNTEC_CMD_ERR_WRONG_NUMBER_OF_ARGUMENTS);
		}
		else
		{
			//uint16_t buf_char_uuid ;
			uint8_t i,j;
			uint8_t value[MAX_VALUE_LENGTH];
			//uint8_t buf[20];
//			uint8_t buf_char_uuid_type;
			ble_uuid_t buf_service_uuid;
			ble_uuid_t buf_char_uuid;
			uint8_t valueLengthBuffer;
			bool readmatchFlag = false;
						// debug message
//						sprintf((char *)&debugMess[0],"buf_char_uuid:[%04X]", buf_char_uuid);
//						console.printf(debugMess);
			uint8_t argLen = 0;
			uint8_t *arg = cyntecGetCommandArgument(0,&argLen);
			
			// Print out the service & char uuids table
//			for (  i = 0 ; i < CLI_SERVICE_MAX_NUM ; i++ )
//		{
//			for (  j = 0 ; j < CLI_SERVICE_MAX_NUM ; j++ )
//			{
//				sprintf((char *)&debugMess[0],"[%4X,%d][%4X,%d]\r\n",bufferService[i].service_uuid.uuid,bufferService[i].service_uuid.type,bufferService[i].bufferGattChar[j].char_uuid.uuid,bufferService[i].bufferGattChar[j].char_uuid.type);
//			console.printf(debugMess);
//					}
//		}

			// Handle input parameter - Service UUID
			if (argLen == 6 && arg[0] == '0' && arg[1] == 'x')
			{
				buf_service_uuid.uuid = cyntecArgToUint16( (arg + 2), (argLen - 2));
				buf_service_uuid.type = BLE_UUID_TYPE_BLE;
			}
			if (argLen == 34 && arg[0] == '0' && arg[1] == 'x')
			{
				buf_service_uuid.uuid = cyntecArgToUint16( (arg + 6), 4);
				buf_service_uuid.type = BLE_UUID_TYPE_VENDOR_BEGIN;
			}
			
			// Handle input parameter -  Characteristic UUID
			argLen = 0;
			arg = cyntecGetCommandArgument(1,&argLen);
			if (argLen == 6 && arg[0] == '0' && arg[1] == 'x')
			{
				buf_char_uuid.uuid = cyntecArgToUint16( (arg + 2), (argLen - 2));
				buf_char_uuid.type = BLE_UUID_TYPE_BLE;
			}
			if (argLen == 34 && arg[0] == '0' && arg[1] == 'x')
			{
				buf_char_uuid.uuid = cyntecArgToUint16( (arg + 6), 4);
				buf_char_uuid.type = BLE_UUID_TYPE_VENDOR_BEGIN;
			}
//			sprintf((char *)&debugMess[0],"buf_service_uuid[%d,%4X]\r\n",buf_service_uuid.type,buf_service_uuid.uuid);
//			console.printf(debugMess);
						for ( i = 0 ; i < CLI_SERVICE_MAX_NUM ; i++ )
						{
							if ( (bufferService[i].service_uuid.uuid == buf_service_uuid.uuid) &(bufferService[i].service_uuid.type == buf_service_uuid.type)& (readmatchFlag == false))
							{
									//readmatchFlag = true;
									for ( j = 0 ; j < CLI_CHAR_MAX_NUM ; j++ )
									{
										if ( (bufferService[i].bufferGattChar[j].char_uuid.uuid == buf_char_uuid.uuid) &(bufferService[i].bufferGattChar[j].char_uuid.type == buf_char_uuid.type)& (readmatchFlag == false))
										{
		//									uint8_t value[] = "88";
											uint16_t len = MAX_VALUE_LENGTH;
											ble_gatts_value_t bufGattsValue;
											memset(&bufGattsValue, 0, sizeof(bufGattsValue));
											bufGattsValue.len = len;
											bufGattsValue.offset = 0;
											bufGattsValue.p_value = value;
											//sd_ble_gatts_value_get(bufferService[i].bufferGattChar[j].char_value_handle,
//														 0,
//														 &len,
//														 value);
											sd_ble_gatts_value_get( test_conn_handle,
																	bufferService[i].bufferGattChar[j].char_value_handle,
																	&bufGattsValue
											);
											console.printf("\r\nOK;0x");
											valueLengthBuffer = bufferService[i].bufferGattChar[j].valueLength;
		//									sprintf((char *)&debugMess[0],"[%i]",valueLengthBuffer);
		//									console.printf(debugMess);
											
											for (i=0 ; i < valueLengthBuffer; i++)
											{
												console.printf("%02X",value[i]);
											}
											console.printf(";\r\n");
											readmatchFlag = true;
											return;
									}
								}
						}
					}
						// no matched case, can not read
						if (readmatchFlag == false){
							cyntecPrintError(CYNTEC_CMD_ERR_NO_MATCHED_ARGUMENT);
						}
				}
				
	
}
/* Set characteristics */
static void cyntecInsertCharUUID(ble_uuid_t char_UUID, uint16_t charValueHandle,uint8_t valueLengthBuffer,uint8_t mode)
{
		uint8_t j;
		j=char_count;
//			sprintf((char *)&debugMess[0],"char_uuid:%4X\r\n",char_UUID.uuid);
//			console.printf(debugMess);	
		bufferService[service_count-1].bufferGattChar[j].char_uuid.uuid = char_UUID.uuid;
		bufferService[service_count-1].bufferGattChar[j].char_uuid.type = char_UUID.type;
		bufferService[service_count-1].bufferGattChar[j].valueLength = valueLengthBuffer;
		bufferService[service_count-1].bufferGattChar[j].mode = mode;
		bufferService[service_count-1].bufferGattChar[j].char_value_handle = charValueHandle;
		return;
}

static void cynGattCharCommand(void)
{
//	uint16_t 					service_uuid_ble;
//	uint8_t 					service_uuid_vs[16];

	uint8_t 					attrMode=0; 
	uint8_t 					attrValue[MAX_VALUE_LENGTH];
	memset(&attrValue, 0, sizeof(attrValue));
	
	uint8_t 					i;
//	uint8_t 					valueBuffer;
	uint8_t 					err_code;
	uint16_t 					buffer_char_uuid;
//	uint16_t          buffer_char_uuid_ble;
	uint16_t       		buffer_uuid_vs[8];
	ble_uuid_t        char_uuid;
	ble_uuid128_t     char_uuid_vs;
	
	ble_gatts_char_md_t char_md;
  ble_gatts_attr_t    attr_char_value;
    
	ble_gatts_attr_md_t cccd_md;
  ble_gatts_attr_md_t attr_md;
//    uint8_t             init_value_encoded[2] = "77";	
//  uint8_t             init_value_len;
	uint8_t 						valueLengthBuffer;
	extern uint8_t 			char_count;
	
	if (cyntecGetCommandTokenCnt() != 5)
	{
		cyntecPrintError(CYNTEC_CMD_ERR_WRONG_NUMBER_OF_ARGUMENTS);
		return;
	}
	else
	{
				
//#ifdef DELTA_DEBUG			
//sprintf((char *)&debugMess[0],"[%04X]", service_uuid);
//console.printf(debugMess);
//#endif
			
			/* handle second parameter -  UUID */
			uint8_t argLen = 0;
			uint8_t *arg = cyntecGetCommandArgument(0,&argLen);
			
			/* len: 6 => 0xXXXX */
			if ( argLen == 6 && arg[0] == '0' && arg[1] == 'x')
			{				
					buffer_char_uuid = cyntecArgToUint16( (arg + 2), (argLen - 2));
					BLE_UUID_BLE_ASSIGN(char_uuid, buffer_char_uuid);
				char_uuid.type = BLE_UUID_TYPE_BLE;
			}
			
			if ( argLen == 34 && arg[0] == '0' && arg[1] == 'x' )
			{
					for ( i=0;i<8;i++)
					{
						buffer_uuid_vs[7-i] = cyntecArgToUint16( (arg + 2+4*i), 4);
						if (i==1)
						{
							char_uuid.uuid = cyntecArgToUint16( (arg + 2+4*i), 4);
						}
//#ifdef DELTA_DEBUG
//						sprintf((char *)&debugMess[0],"%2X/",buffer_uuid_vs[7-i]);
//						console.printf(debugMess);
//#endif
					}
					memcpy(&char_uuid_vs,buffer_uuid_vs,16);
					err_code = sd_ble_uuid_vs_add(&char_uuid_vs, &char_uuid.type);
			}
//#ifdef DELTA_DEBUG
//			sprintf((char *)&debugMess[0],"char_uuid_type:[%d]\r\n",char_uuid.type);
//						console.printf(debugMess);
//#endif
					
					
//#ifdef DELTA_DEBUG 
//					sprintf((char *)&debugMess[0],"vs_add_Error:%d\r\n",err_code);
//						console.printf(debugMess);
//#endif 
			
			/* handle 3rd parameter -  attribute mode */
			argLen = 0;
			arg = cyntecGetCommandArgument(1,&argLen);
		
			for ( i = 0 ; i < argLen ; i++ )
			{
				switch(arg[i]) {
					case 'r':
						attrMode |= (1 << CLI_CHAR_MODE_READ);
						break;
					case 'w':
						attrMode |= (1 << CLI_CHAR_MODE_WRITE);
						break;
					case 'i':
						attrMode |= (1 << CLI_CHAR_MODE_INDICATE);
						break;
					case 'n':
						attrMode |= (1 << CLI_CHAR_MODE_NOTIFY);
						break;
					default:
						break;
				}
			}
			
			/* handle 4th parameter -  attribute value */
			argLen = 0;
			arg = cyntecGetCommandArgument(2,&argLen);
			
			if (arg[0] != '0' || arg[1] != 'x' | argLen%2 != 0) {
				cyntecPrintError(CYNTEC_CMD_ERR_ARGUMENT_SYNTAX_ERROR);
				return;					 
			  }
			else {
				valueLengthBuffer = (argLen-2)/2;
       for (i=0 ; i < (argLen-2)/2; i++)
				{
					attrValue[i]  = cyntecArgToUint8(arg+2*(i+1), 2);
					
				}
					//cyntecInsertCharUUID(service_uuid, char_uuid, attrMode, attrValue,valueLengthBuffer);
					//cyntecPrintOk();
				}
		  }
			
	
    		//debug
//    sprintf((char *)&debugMess[0],"value:[%02X][%02X]", value[0],value[1]);
//		console.printf(debugMess);
	
		//write read permission
		ble_gap_conn_sec_mode_t local_all_perm;
		local_all_perm.lv = 1;
		local_all_perm.sm = 1;
		
		memset(&cccd_md, 0, sizeof(cccd_md));
    BLE_GAP_CONN_SEC_MODE_SET_OPEN(&cccd_md.read_perm);
    cccd_md.write_perm = local_all_perm;
    cccd_md.vloc       = BLE_GATTS_VLOC_STACK;
	
    memset(&char_md, 0, sizeof(char_md));
    
		if ( attrMode & (1 << CLI_CHAR_MODE_READ))
			char_md.char_props.read  = 1;
		if (attrMode & (1 << CLI_CHAR_MODE_WRITE))
			char_md.char_props.write = 1;
		if (attrMode & (1 << CLI_CHAR_MODE_NOTIFY))
			char_md.char_props.notify = 1;
		if (attrMode & (1 << CLI_CHAR_MODE_INDICATE)) 
			char_md.char_props.indicate = 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;
    
    memset(&attr_md, 0, sizeof(attr_md));

    attr_md.vloc       = BLE_GATTS_VLOC_STACK;
    attr_md.read_perm  = local_all_perm;
    attr_md.write_perm = local_all_perm;
    attr_md.rd_auth    = 0;
    attr_md.wr_auth    = 0;
    attr_md.vlen       = 0;
    
    memset(&attr_char_value, 0, sizeof(attr_char_value));
    
//		init_value_len = MAX_VALUE_LENGTH;

    attr_char_value.p_uuid       = &char_uuid;
    attr_char_value.p_attr_md    = &attr_md;
    attr_char_value.init_len     = MAX_VALUE_LENGTH;
    attr_char_value.init_offs    = 0;
    attr_char_value.max_len      = MAX_VALUE_LENGTH;
    attr_char_value.p_value      = attrValue;
		//debug
//    sprintf((char *)&debugMess[0],"value:[%s]", attr_char_value.p_value);
//		console.printf(debugMess);
    ble_gatts_char_handles_t testHandle;
     err_code = sd_ble_gatts_characteristic_add(bufferGattTest.service_handle,
                                           &char_md,
                                           &attr_char_value,
                                           &testHandle);
//#ifdef DELTA_DEBUG
//			sprintf((char *)&debugMess[0],"char_uuid:%4X\r\n",char_uuid.uuid);
//			console.printf(debugMess);												 
//#endif
	  if (err_code == NRF_SUCCESS)
		{
			cyntecPrintOk();
			cyntecInsertCharUUID(char_uuid, testHandle.value_handle,valueLengthBuffer,attrMode);
//			sprintf((char *)&debugMess[0],"char_count:%d\r\n",char_count);
//			console.printf(debugMess);	
			char_count++;
			if (char_count>10)
				char_count=0;
		}
		else if (err_code == NRF_ERROR_INVALID_STATE)
		{
			cyntecPrintError(CYNTEC_CMD_ERR_INVALID_STATE_TO_PERFORM_OPERATION);
			return;
		}
		else
		{
			console.printf("ERROR;\r\n");				
		}

}

static void cyntecInsertServiceUUID(ble_uuid_t service_UUID)
{	
	/* find if the service uuid is exist */			
				bufferService[service_count].service_uuid.uuid = service_UUID.uuid;
				bufferService[service_count].service_uuid.type = service_UUID.type;
				return;

}

static void cynGattServiceCommand(void)
{
//	uint16_t service_uuid;
//	uint8_t attrValue[MAX_VALUE_LENGTH];
//	memset(&attrValue, 0, sizeof(attrValue));
//	uint8_t i;
//	uint8_t valueBuffer;
	extern uint8_t service_count;
	
	uint32_t   err_code;	
	ble_uuid_t ble_uuid;
	ble_uuid128_t ble_uuid128;
	uint16_t buffer_uuid;
	uint16_t buffer_uuid_vs[8];
	int i;
	
	if (cyntecGetCommandTokenCnt() != 3)
	{
		cyntecPrintError(CYNTEC_CMD_ERR_WRONG_NUMBER_OF_ARGUMENTS);
		return;
	}
	else
	{
			/* handle first parameter - Service UUID */
			uint8_t argLen = 0;
			uint8_t *arg = cyntecGetCommandArgument(0,&argLen);

			/* Service uuid is 16 bits */
			if ( argLen == 6 && arg[0] == '0' && arg[1] == 'x')
			{
					buffer_uuid = cyntecArgToUint16( (arg + 2), (argLen - 2));
					//ble_uuid.type = BLE_UUID_TYPE_BLE; //type assign in BLE_UUID_BLE_ASSIGN
					BLE_UUID_BLE_ASSIGN(ble_uuid, buffer_uuid);
				
					err_code = sd_ble_gatts_service_add(BLE_GATTS_SRVC_TYPE_PRIMARY, &ble_uuid, &bufferGattTest.service_handle);
					ble_uuid.type = BLE_UUID_TYPE_BLE;
				
			}
		 
			/* Service uuid is 128 bits */
			if ( argLen == 34 && arg[0] == '0' && arg[1] == 'x' )
			{
//					uint8_t uuid_type = custom_add_uuid_base(CFG_CUSTOM_UUID_BASE);
					//ASSERT(uuid_type > 0, ERROR_NOT_FOUND);
					for ( i=0;i<8;i++)
					{
						buffer_uuid_vs[7-i] = cyntecArgToUint16( (arg + 2+4*i), 4);
						if (i==1)
						{
							ble_uuid.uuid = cyntecArgToUint16( (arg + 2+4*i), 4);
						}
#ifdef DELTA_DEBUG
						console.printf("%2X/",buffer_uuid_vs[7-i]);
#endif
					}
					memcpy(&ble_uuid128.uuid128,buffer_uuid_vs,16);
//#ifdef DELTA_DEBUG
//					sprintf((char *)&debugMess[0],"%32X\r\n",ble_uuid128.uuid128);
//					console.printf(debugMess);
//#endif
					err_code = sd_ble_uuid_vs_add(&ble_uuid128, &ble_uuid.type);
//#ifdef DELTA_DEBUG 
//					sprintf((char *)&debugMess[0],"service_uuid_type:%d\r\n",ble_uuid.type);
//						console.printf(debugMess);
//#endif 

					err_code = sd_ble_gatts_service_add(BLE_GATTS_SRVC_TYPE_PRIMARY, &ble_uuid, &bufferGattTest.service_handle);
					
					ble_uuid.type = BLE_UUID_TYPE_VENDOR_BEGIN;
				
			}
			if (err_code == NRF_SUCCESS)
					{
						cyntecPrintOk();
						cyntecInsertServiceUUID(ble_uuid);
						service_count++;
						char_count = 0;
//						sprintf((char *)&debugMess[0],"service_count:%d\r\n",service_count);
//						console.printf(debugMess);
					}
			else
			{
				console.printf("ERROR;\r\n");
				
			}
			
		}
	}

static void cynBLEInitCommand(void)
{
		const char DEVICE_NAME[] = "DELTA_CLI";
	
		deltaBLE.init();
		deltaBLE.onDisconnection(disconnectionCallback);
		deltaBLE.onConnection(onConnectionCallback);
		deltaBLE.onTimeout(onTimeoutCallback);
	
		/* Setup advertising. */
		deltaBLE.accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED | GapAdvertisingData::LE_GENERAL_DISCOVERABLE);
		deltaBLE.accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LOCAL_NAME, (uint8_t *)DEVICE_NAME, sizeof(DEVICE_NAME));
		deltaBLE.setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED);
		deltaBLE.setAdvertisingInterval(1000);
	
		cyntecPrintOk();
}

CyntecCommandEntry bleCommandSets[] = {
	{"init", cynBLEInitCommand, NULL, "Init BLE stack, Usage: cynb init"},
	{"gpio", cynBLEGPIOCommand, NULL, "Config gpio, Usage: cynb gpio <GPIO NO> <set|clear>"},
	{"sleep", cynBLESystemOffCommand, NULL, "System off mode, Usage: cynb sleep <GPIO NO>"},
	{"disconn", cynBLEDisconnectCommand, NULL, "Disconnection, Usage: cynb disconn"},
  {"reset", cynResetCommand, NULL, "Soft reset, Usage: cynb reset"},
	{"info", cynBLEInfoCommand, NULL, "Module information, Usage: cynb info"},
#ifdef S110_BLE_PERIPHERAL
	{"gattChar", cynGattCharCommand, NULL, "Set SIG defined characteristic or Create your own"},
	{"gattService", cynGattServiceCommand, NULL, "Set SIG defined service or Create your own"},
  {"name", cynBLENameCommand, NULL, "Set/Get friendly for BLE module"},	
  {"advStart", cynAdvertiseStartCommand, NULL, "Start broadcast advertise packet"},
	{"advStop", cynAdvertiseStopCommand, NULL, "Stop broadcast advertise packet"},
#endif
#ifdef S120_BLE_CENTRAL
	{"scan", cynBLEScanCommand, NULL, "Start/Stop(1/0) to scan BLE device"},
	{"connect", cynBLEConnectCommand, NULL, "Connect to specific BLE device by Device Name"},	
#endif
  {"txPow", cynBLESetTxPowerCommand, NULL, "Set BLE tx power"},
	{"bleAddr", cynBLEAddressCommand, NULL, "Set/Get Bluetooth address"},
	{"update", cynBLEUpdateUUIDCommand, NULL, "Update value of specific characteristics"},
	{"readData", cynBLEReadDataCommand, NULL, "Read value of specific characteristics"},
  {NULL, NULL, NULL, NULL},
};