Delta / Mbed OS Delta_CLI

Fork of NNN40_CLI by Delta

Revision:
16:d1682a3e93f5
Parent:
15:d627ee60bb78
Child:
17:03c8af30087a
diff -r d627ee60bb78 -r d1682a3e93f5 CLI_Source/ble_cli.cpp
--- a/CLI_Source/ble_cli.cpp	Mon Apr 25 10:58:14 2016 +0000
+++ b/CLI_Source/ble_cli.cpp	Thu Sep 08 07:10:20 2016 +0000
@@ -10,7 +10,7 @@
 // Genral configuration parameters
 #define BLE_DEBUG  0
 #define MAX_DEVNAME_LEN 32
-#define CLI_FWVERION "DELTA_CLI_V1.13"
+#define CLI_FWVERION "DELTA_CLI_V1.14"
 #define MODULE_NAME "DFCM-NNN40-DT1R"
 
 // Advertising configuration parameters
@@ -54,6 +54,8 @@
 /*************** General parameters**********************************/
 bufferGattService_t bufferService[CLI_SERVICE_MAX_NUM]; /* save entry services */
 static GattCharacteristic *charAry[CLI_SERVICE_MAX_NUM][CLI_CHAR_MAX_NUM];
+DiscoveredService discoverServiceArr[CLI_SERVICE_MAX_NUM]; //Silvia add
+DiscoveredCharacteristic discoverCharArr[CLI_SERVICE_MAX_NUM][CLI_CHAR_MAX_NUM]; //Silvia add
 extern Serial console;
 BLE deltaBLE; //gill 0904
 extern const char* cyntecCommandErrorNames[];
@@ -63,10 +65,14 @@
 static bool connState = false; // gill 0904, define currently connecting state
 static uint8_t service_count=0;
 static uint8_t char_count=0;
+static uint8_t discoverService_count=0; //Silvia add
+static uint8_t discoverChar_count=0; //Silvia add
 static uint16_t test_conn_handle; //Connection handle, assign after trigger onConnectionCallback
 //extern bool advState; // currently no use
 static Gap::Address_t saveAddr[BLE_MAX_ADDRESS_NUMBER]; // check in advertisementCallback
 static uint8_t bleDevInd;
+//static const unsigned ADDR_LEN = BLEProtocol::ADDR_LEN; //Silvia add, Length (in octets) of the BLE MAC address
+static BLEProtocol::AddressBytes_t targetAddr; //Silvia add, For connect target device
 static char targetDevName[TARGET_DEVNAME_LEN]; // For connect target device
 //static char DEVICE_NAME[] = "nRF5x"; // default device name, same as defined in Gap.h
 static bool conn_action = false; // Gill add 20151015
@@ -75,6 +81,7 @@
 //DigitalOut led2(p13);
 DigitalOut BLEWriteInt(p13); // used in OnDataWritten()
 
+
 /******************************************************
  *               Function Definitions
  ******************************************************/
@@ -83,7 +90,7 @@
 
 void serviceDiscoveryCallback(const DiscoveredService *service)
 {
-    console.printf("serviceDiscoveryCallback\r\n");
+    printf("serviceDiscoveryCallback\r\n");
     if (service->getUUID().shortOrLong() == UUID::UUID_TYPE_SHORT) {
         printf("S UUID-%x attrs[%u %u]\r\n", service->getUUID().getShortUUID(), service->getStartHandle(), service->getEndHandle());
     } else {
@@ -94,16 +101,30 @@
         }
         printf(" attrs[%u %u]\r\n", service->getStartHandle(), service->getEndHandle());
     }
+    
+    discoverServiceArr[discoverService_count] = *service;
+    discoverService_count++;
+    discoverChar_count = 0;
 }
 
 void characteristicDiscoveryCallback(const DiscoveredCharacteristic *characteristicP)
 {
-    console.printf("characteristicDiscoveryCallback\r\n");
-    //printf("  C UUID-%x valueAttr[%u] props[%x]\r\n", characteristicP->getShortUUID(), characteristicP->getValueHandle(), (uint8_t)characteristicP->getProperties().broadcast());
-    //if (characteristicP->getShortUUID() == 0xa001) { /* !ALERT! Alter this filter to suit your device. */
-    //if(1) {
-//        ledCharacteristic        = *characteristicP;
-//    }
+    //Silvia modify
+    if (characteristicP->getUUID().shortOrLong() == UUID::UUID_TYPE_SHORT) {
+        printf("  C UUID-%x valueAttr[%u] props[%x]\r\n", characteristicP->getUUID().getShortUUID(), characteristicP->getValueHandle(), (uint8_t)characteristicP->getProperties().broadcast());
+    }
+    else {
+        printf("  C UUID-");
+        const uint8_t *longUUIDBytes = characteristicP->getUUID().getBaseUUID();
+        for (unsigned i = (UUID::LENGTH_OF_LONG_UUID) - 1; i < UUID::LENGTH_OF_LONG_UUID; i--) {
+            printf("%02x ", longUUIDBytes[i]);
+        }
+        printf(" valueAttr[%u] props[%x]\r\n", characteristicP->getValueHandle(), (uint8_t)characteristicP->getProperties().broadcast());
+//        uvCharacteristic        = *characteristicP;
+    }
+    
+    discoverCharArr[discoverService_count - 1][discoverChar_count] = *characteristicP;
+    discoverChar_count++;
 }
 void discoveryTerminationCallback(Gap::Handle_t connectionHandle)
 {
@@ -117,20 +138,39 @@
 #if BLE_DEBUG
     console.printf("Connect: connState write to %d\r\n",connState);
 #endif
-    // gill test
-    //if (params->role == Gap::CENTRAL) {
-//        //deltaBLE.gattClient().onServiceDiscoveryTermination(discoveryTerminationCallback);
-//        deltaBLE.gattClient().launchServiceDiscovery(params->handle, serviceDiscoveryCallback, characteristicDiscoveryCallback, 0xa000, 0xa001);
-//    }
+    //Silvia modify
+    if (params->role == Gap::CENTRAL) {
+        deltaBLE.gattClient().onServiceDiscoveryTermination(discoveryTerminationCallback);
+        deltaBLE.gattClient().launchServiceDiscovery(test_conn_handle, serviceDiscoveryCallback, characteristicDiscoveryCallback);
+    }
+    //Silvia modify
 }
 
 void onTimeoutCallback(Gap::TimeoutSource_t source)
 {
     //led1 = !led1;
+    
+    //Silvia add
+    switch (source) {
+    	case Gap::TIMEOUT_SRC_ADVERTISING:
+    		printf("Advertising timeout\r\n");
+    		break;	
+    	case Gap::TIMEOUT_SRC_SECURITY_REQUEST:
+    		printf("Security request timeout\r\n");
+    		break;
+    	case Gap::TIMEOUT_SRC_SCAN:
+    		printf("Scanning timeout\r\n");
+    		break;
+    	case Gap::TIMEOUT_SRC_CONN:
+    		printf("Connection timeout\r\n");
+    		break;
+    }
+    //Silvia add
 }
 
 void disconnectionCallback(const Gap::DisconnectionCallbackParams_t *params)
 {
+    printf("Disconnected\r\n"); //Silvia add
     //console.printf("connState:%d\r\n",connState);
     //Gap::GapState_t->connected = 0;
     connState = false;
@@ -269,52 +309,7 @@
     //nrf_gpio_pin_clear(ADVERTISING_LED_PIN_NO);
 }
 
-//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 = '*';
-//        if (!memcmp(&argName1[0],&bracket,sizeof(char)) && !memcmp(&argNameLast[tempNameLen - 1],&bracket,sizeof(char)))
-//        {
-//            uint8_t nameLen = 0;
-//            uint8_t * argName2 = cyntecGetCommandTotalBuffer();
-//            uint32_t err_code;
-//            ble_gap_conn_sec_mode_t sec_mode;
-//            uint8_t i = 0;
-//            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) {
-//                console.printf("\r\nOK;");
-//                for(i = 0; i < cyntecGetTotalIndex()-12; i++) {
-//                    console.printf("%c",argName2[11+i]);
-//                }
-//                console.printf("\r\n");
-//            } else {
-//                console.printf("ERROR;%04X\r\n",err_code);
-//            }
-//        } 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);
-//        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;
-//    }
-//}
-
+//Silvia modify
 static void cynBLENameCommand(void)
 {
     uint8_t nameLen = 0; // Name char number, max is TARGET_DEVNAME_LEN
@@ -355,9 +350,7 @@
 #endif
     }
 }
-
-
-
+//Silvia modify
 
 static void cynBLEInfoCommand(void)
 {
@@ -458,9 +451,9 @@
         err_code = sd_ble_gap_address_get(&m_peer_addr);
         //APP_ERROR_CHECK(err_code);
 
-        cyntecPrintOk();
+//        cyntecPrintOk();
 
-        console.printf("[%02X %02X %02X %02X %02X %02X]",
+        console.printf("OK;[%02X %02X %02X %02X %02X %02X];\r\n",
                        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
@@ -492,48 +485,59 @@
 
 void advertisementCallback(const Gap::AdvertisementCallbackParams_t *params)
 {
-    bool flagRepeat=false;
+    //Silvia modify
     Gap::Address_t newAddr[6];
     memcpy(newAddr,params->peerAddr,6);
-
-    for(int i=0; i<BLE_MAX_ADDRESS_NUMBER; i++) {
-        if (memcmp(newAddr,saveAddr[i],6)==0) {
-#if BLE_DEBUG
-            console.printf("Repeated\r\n");
-#endif
-            flagRepeat = true;
-            //return;
+    
+    if (conn_action == true) {
+        conn_action = false;
+        
+        if (memcmp(targetAddr,newAddr,6)==0) {
+			deltaBLE.gap().connect(params->peerAddr, Gap::ADDR_TYPE_RANDOM_STATIC, NULL, NULL);
+            return;
         }
-    }
+    } else {
+    	bool flagRepeat=false;
+    	
+    	for(int i=0; i<BLE_MAX_ADDRESS_NUMBER; i++) {
+        	if (memcmp(newAddr,saveAddr[i],6)==0) {
+				#if BLE_DEBUG
+            	console.printf("Repeated\r\n");
+				#endif
+            	flagRepeat = true;
+            	//return;
+        	}
+    	}
 
-#if BLE_DEBUG
-    console.printf("addr cmp result :%i\r\n",memcmp(newAddr,params->peerAddr,6));
-    console.printf("ADV data:%X,%i\r\n",&(params->advertisingData),params->advertisingDataLen);
-#endif
-    data_t adv_data;
-    data_t type_data;
-    //Initialize advertisement report for parsing.
-    adv_data.p_data = params->advertisingData;
-    adv_data.data_len = params->advertisingDataLen;
-    // Parsing Device Name
-    uint32_t err_code = adv_report_parse(BLE_GAP_AD_TYPE_COMPLETE_LOCAL_NAME,
-                                         &adv_data,
-                                         &type_data);
-#if BLE_DEBUG
-    console.printf("error code:%X\r\n",err_code);
-    console.printf("type_data.data_len:%i\r\n",type_data.data_len);
-#endif
-    if (flagRepeat == false) {
-        if (err_code == 0) {
-            for (int i=0; i<type_data.data_len; i++) {
-                console.printf("%c",type_data.p_data[i]);
-            }
-            //console.printf("\r\n");
-        }
-        console.printf(",ADV,[%02X %02X %02X %02X %02X %02X],%d,%u\r\n",params->peerAddr[5], params->peerAddr[4], params->peerAddr[3],
-                       params->peerAddr[2], params->peerAddr[1], params->peerAddr[0],params->rssi,params->type);
-        memcpy(saveAddr[bleDevInd],params->peerAddr,6);
-        bleDevInd++;
+		#if BLE_DEBUG
+    	console.printf("addr cmp result :%i\r\n",memcmp(newAddr,params->peerAddr,6));
+    	console.printf("ADV data:%X,%i\r\n",&(params->advertisingData),params->advertisingDataLen);
+		#endif
+    	data_t adv_data;
+    	data_t type_data;
+    	//Initialize advertisement report for parsing.
+    	adv_data.p_data = params->advertisingData;
+    	adv_data.data_len = params->advertisingDataLen;
+    	// Parsing Device Name
+    	uint32_t err_code = adv_report_parse(BLE_GAP_AD_TYPE_COMPLETE_LOCAL_NAME,
+                                         	&adv_data,
+                                         	&type_data);
+		#if BLE_DEBUG
+    	console.printf("error code:%X\r\n",err_code);
+    	console.printf("type_data.data_len:%i\r\n",type_data.data_len);
+		#endif
+    	if (flagRepeat == false) {
+        	if (err_code == 0) {
+            	for (int i=0; i<type_data.data_len; i++) {
+                	console.printf("%c",type_data.p_data[i]);
+            	}
+            	//console.printf("\r\n");
+        	}
+        	console.printf(",ADV,[%02X %02X %02X %02X %02X %02X],%d,%u\r\n",params->peerAddr[5], params->peerAddr[4], params->peerAddr[3],
+                       		params->peerAddr[2], params->peerAddr[1], params->peerAddr[0],params->rssi,params->type);
+        	memcpy(saveAddr[bleDevInd],params->peerAddr,6);
+        	bleDevInd++;
+    	}
     }
 
     /*
@@ -549,10 +553,6 @@
 //    	console.printf("%s\r\n",type_data.p_data);
 //
 //    }
-    if (conn_action == true) {
-        conn_action = false;
-        deltaBLE.gap().connect(params->peerAddr, Gap::ADDR_TYPE_RANDOM_STATIC, NULL, NULL);
-    }
 }
 
 
@@ -560,6 +560,7 @@
  */
 static void scan_start(void)
 {
+    memset(saveAddr,0,sizeof(saveAddr)); //Silvia add, Clear saving address set
     deltaBLE.gap().startScan(advertisementCallback);
     //APP_ERROR_CHECK(err_code);
 }
@@ -593,7 +594,7 @@
 #if BLE_DEBUG
     console.printf("Interval:%d,Window:%d,timeout:%d\r\n",setInterval,setWindow,setTimeout);
 #endif
-    memset(saveAddr,0,sizeof(saveAddr)); // Clear saving address set
+//    memset(saveAddr,0,sizeof(saveAddr)); // Clear saving address set
     //deltaBLE.gap().setScanParams(setInterval,setWindow,setTimeout,false);
     deltaBLE.gap().setScanInterval(setInterval);
     deltaBLE.gap().setScanWindow(setWindow);
@@ -611,31 +612,76 @@
 
 static void cynBLEConnectCommand(void)
 {
+    //Silvia modify for specific address
     if (cyntecGetCommandTokenCnt() != 3) {
         cyntecPrintError(CYNTEC_CMD_ERR_WRONG_NUMBER_OF_ARGUMENTS);
         return;
     }
+    uint8_t argLen = 0;
+    uint8_t *arg = cyntecGetCommandArgument(0, &argLen);
+    ble_error_t err_code;
+    uint8_t addr,i;
 
-    uint8_t devNameLen = 0;
-    uint8_t *argDevName = cyntecGetCommandArgument(0, &devNameLen);
+    /* should with "0x" + 12 len addr */
+    if (argLen == 14) {
+        if (arg[0] != '0' || arg[1] != 'x') {
+            cyntecPrintError(CYNTEC_CMD_ERR_ARGUMENT_SYNTAX_ERROR);
+            return;
+        }
+        memset(targetAddr,0,sizeof(targetAddr));
 
-    //if ( argDevName != NULL ) {
-//			uint8_t i;
-//			for (i = 0; i < devNameLen; i++) {
-//				targetDevName[i] = argDevName[i];
-//			}
-//			if (i < devNameLen)
-//				targetDevName[i] = '\0';
-//		}
-
-    memset( targetDevName , 0, TARGET_DEVNAME_LEN);
-    memcpy( targetDevName, argDevName, devNameLen);
-#if BLE_DEBUG
-    console.printf("Search for device name:%s\r\n",argDevName);
-    console.printf("Target:%s\r\n",targetDevName);
-#endif
-    conn_action = true;
-    scan_start();
+        for ( i = 1 ; i < 7 ; i++) {
+            addr = cyntecArgToUint8(arg+2*i, 2);
+            /* 5 - (i-1) */
+            targetAddr[6-i] = addr;
+        }
+        
+        for(int i=0; i<BLE_MAX_ADDRESS_NUMBER; i++) {
+        	if (memcmp(targetAddr,saveAddr[i],6)==0) {
+				err_code = deltaBLE.gap().connect(targetAddr, Gap::ADDR_TYPE_RANDOM_STATIC, NULL, NULL);
+        
+        		if (err_code != 0) {
+        			printf("Error:%d\r\n",err_code);
+        		} else {
+        			cyntecPrintOk();
+        		}
+        		
+        		return;
+        	}
+    	}
+    	
+    	conn_action = true;
+    	scan_start();  
+    } else {  //argLen != 14
+        cyntecPrintError(CYNTEC_CMD_ERR_ARGUMENT_SYNTAX_ERROR);
+        return;
+    } 
+    
+    //if (cyntecGetCommandTokenCnt() != 3) {
+//        cyntecPrintError(CYNTEC_CMD_ERR_WRONG_NUMBER_OF_ARGUMENTS);
+//        return;
+//    }
+//
+//    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';
+////		}
+//
+//    memset( targetDevName , 0, TARGET_DEVNAME_LEN);
+//    memcpy( targetDevName, argDevName, devNameLen);
+//#if BLE_DEBUG
+//    console.printf("Search for device name:%s\r\n",argDevName);
+//    console.printf("Target:%s\r\n",targetDevName);
+//#endif
+//    conn_action = true;
+//    scan_start();
 
 }
 
@@ -747,6 +793,35 @@
 //        ledCharacteristic.write(1, &toggledValue);
 //    }
 }
+
+//Silvia modify
+void centralReadCallback(const GattReadCallbackParams *response) {
+//    printf("centralReadCallback Handle: %d\r\n", response->handle);
+    
+    for (unsigned index = 0; index < response->len; index++) {
+        printf("[%02x]", response->data[index]);
+    }
+    printf("\r\n");
+}
+
+void centralWriteCallback(const GattWriteCallbackParams *response) {
+//    printf("centralWriteCallback: %d\r\n", response->len);
+    
+    for (unsigned index = 0; index < response->len; index++) {
+        printf("[%02x]", response->data[index]);
+    }
+    printf("\r\n");
+}
+
+void centralHvxCallback(const GattHVXCallbackParams *response) {
+//	printf("centralHvxCallback handle %u, type %02x, len %u\r\n", response->handle, response->type, response->len);
+    for (unsigned index = 0; index < response->len; index++) {
+        printf("[%02x]", response->data[index]);
+    }
+    printf("\r\n");
+}
+//Silvia modify
+
 static void cynBLEUpdateDataCommand(void)
 {
     if (cyntecGetCommandTokenCnt() != 6) {
@@ -911,12 +986,12 @@
                 if (( bufferService[i].bufferGattChar[j].char_uuid == buf_char_uuid)& (readmatchFlag == false)) {
                     GattAttribute& valueAttr = charAry[i][j]->getValueAttribute();
 //                    valueLenPtr = valueAttr.getLengthPtr();
-                  valueLen = bufferService[i].bufferGattChar[j].valueLength;
-										uint16_t * valueLenPtr = &bufferService[i].bufferGattChar[j].valueLength;
+                  	valueLen = bufferService[i].bufferGattChar[j].valueLength;
+					uint16_t * valueLenPtr = &bufferService[i].bufferGattChar[j].valueLength;
                     ble_error_t err = deltaBLE.gattServer().read(valueAttr.getHandle(),bufVal,valueLenPtr);
 #if BLE_DEBUG
                     console.printf("Read ERR:%i\r\n",err);
-										printf("valueLen:%i\r\n",valueLen);
+					printf("valueLen:%i\r\n",valueLen);
 #endif
                     console.printf("\r\nOK;");
                     console.printf("0x");
@@ -1096,6 +1171,335 @@
 
     cyntecPrintOk();
 }
+
+//Silvia modify
+static void cynBLECenInitCommand(void)
+{
+    deltaBLE.init();
+    deltaBLE.onDisconnection(disconnectionCallback);
+    deltaBLE.onConnection(onConnectionCallback);
+    deltaBLE.onTimeout(onTimeoutCallback);
+    deltaBLE.gattClient().onDataRead(centralReadCallback);
+    deltaBLE.gattClient().onDataWrite(centralWriteCallback);
+    deltaBLE.gattClient().onHVX(centralHvxCallback);
+
+    cyntecPrintOk();
+}
+
+static void cynBLECenReadDataCommand(void)
+{
+	if (cyntecGetCommandTokenCnt() != 4) {
+        cyntecPrintError(CYNTEC_CMD_ERR_WRONG_NUMBER_OF_ARGUMENTS);
+        return;
+    }
+    UUID buf_ser_uuid ;
+    uint8_t bufferUuidVs[16];
+    UUID buf_char_uuid;
+    bool readmatchFlag = false;
+    uint8_t argLen = 0;
+    uint8_t *arg = cyntecGetCommandArgument(0,&argLen);
+
+    // Handle input parameter - Service UUID
+    if ( argLen == 6 && arg[0] == '0' && arg[1] == 'x') {
+        buf_ser_uuid = cyntecArgToUint16( (arg + 2), (argLen - 2));
+    }
+    if ( argLen == 34 && arg[0] == '0' && arg[1] == 'x' ) {
+        for (uint8_t i=0; i<16; i++) {
+            bufferUuidVs[i] = cyntecArgToUint8( (arg + 2+2*i), 2);
+        }
+        buf_ser_uuid.setupLong(bufferUuidVs);
+    }
+
+    // Handle input parameter -  Characteristic UUID
+    argLen = 0;
+    arg = cyntecGetCommandArgument(1,&argLen);
+    if ( argLen == 6 && arg[0] == '0' && arg[1] == 'x') {
+        buf_char_uuid  = cyntecArgToUint16( (arg + 2), (argLen - 2));
+    }
+    if ( argLen == 34 && arg[0] == '0' && arg[1] == 'x' ) {
+        for (uint8_t i=0; i<16; i++) {
+            bufferUuidVs[i] = cyntecArgToUint8( (arg + 2+2*i), 2);
+        }
+        buf_char_uuid.setupLong(bufferUuidVs);
+    }
+    
+    for ( int i = 0 ; i < discoverService_count ; i++ ) {
+    	UUID sUUID, cUUID;
+    	if (discoverServiceArr[i].getUUID().shortOrLong() == UUID::UUID_TYPE_SHORT) {
+        	sUUID = UUID(discoverServiceArr[i].getUUID().getShortUUID());
+    	} else {
+    		const uint8_t *longUUIDBytes = discoverServiceArr[i].getUUID().getBaseUUID();
+    		sUUID = UUID(longUUIDBytes);
+        }
+        if ((sUUID == buf_ser_uuid) & (readmatchFlag == false)) {
+        	for (int j = 0 ; j < CLI_CHAR_MAX_NUM ; j++ ) {
+        		if (discoverCharArr[i][j].getUUID().shortOrLong() == UUID::UUID_TYPE_SHORT) {
+        			cUUID = UUID(discoverCharArr[i][j].getUUID().getShortUUID());
+    			} else {
+    				const uint8_t *longUUIDBytes = discoverCharArr[i][j].getUUID().getBaseUUID();
+    				cUUID = UUID(longUUIDBytes);
+    			}
+    			if ((cUUID == buf_char_uuid) & (readmatchFlag == false)) {
+    				cyntecPrintOk();
+    				discoverCharArr[i][j].read();
+    				
+    				readmatchFlag = true;
+                    return;
+    			}
+        	}
+        }
+    }
+    	
+    // no matched case, can not read
+    if (readmatchFlag == false) {
+        cyntecPrintError(CYNTEC_CMD_ERR_NO_MATCHED_ARGUMENT);
+    }	
+}
+
+static void cynBLECenWriteDataCommand(void) {
+	if (cyntecGetCommandTokenCnt() != 6) {
+        cyntecPrintError(CYNTEC_CMD_ERR_WRONG_NUMBER_OF_ARGUMENTS);
+        return;
+    }
+    UUID buf_ser_uuid ;
+    uint8_t bufferUuidVs[16];
+    UUID buf_char_uuid;
+    bool readmatchFlag = false;
+    uint16_t valueLen = 0;
+    uint8_t argLen = 0;
+    uint8_t *arg = cyntecGetCommandArgument(0,&argLen);
+    uint8_t bufVal[MAX_VALUE_LENGTH] = {0};
+
+    // Handle input parameter - Service UUID
+    if ( argLen == 6 && arg[0] == '0' && arg[1] == 'x') {
+        buf_ser_uuid = cyntecArgToUint16( (arg + 2), (argLen - 2));
+    }
+    if ( argLen == 34 && arg[0] == '0' && arg[1] == 'x' ) {
+        for (uint8_t i=0; i<16; i++) {
+            bufferUuidVs[i] = cyntecArgToUint8( (arg + 2+2*i), 2);
+        }
+        buf_ser_uuid.setupLong(bufferUuidVs);
+    }
+
+    // Handle input parameter -  Characteristic UUID
+    argLen = 0;
+    arg = cyntecGetCommandArgument(1,&argLen);
+    if ( argLen == 6 && arg[0] == '0' && arg[1] == 'x') {
+        buf_char_uuid  = cyntecArgToUint16( (arg + 2), (argLen - 2));
+    }
+    if ( argLen == 34 && arg[0] == '0' && arg[1] == 'x' ) {
+        for (uint8_t i=0; i<16; i++) {
+            bufferUuidVs[i] = cyntecArgToUint8( (arg + 2+2*i), 2);
+        }
+        buf_char_uuid.setupLong(bufferUuidVs);
+    }
+    
+    //// Input Value Type
+	arg = cyntecGetCommandArgument(2,&argLen);
+	uint8_t type = *arg;
+	//type = cyntecArgToUint8(arg,2);
+//	printf("type:%d\r\n",type);
+	if(type != '0' && type != '1') {
+		cyntecPrintError(CYNTEC_CMD_ERR_ARGUMENT_OUT_OF_RANGE);
+	}
+		
+    // Input value
+    arg = cyntecGetCommandArgument(3,&argLen);
+	if(type == '0') {
+		valueLen = argLen; 
+		memcpy(bufVal,arg,argLen);
+	}
+	if(type == '1') {
+		valueLen = (argLen-2)/2; // uint8_t to uint16_t transform
+		for (int i=0 ; i < valueLen; i++) {
+			bufVal[i] = cyntecArgToUint8(arg+2+2*i,2);
+		}
+	}
+#if BLE_DEBUG
+	 printf("type:%i,bufVal:",type);
+	 printf("valueLength:%i\r\n",valueLen);
+	 for (int i=0 ; i < valueLen; i++) {
+		printf("%02X ",bufVal[i]);
+	 }
+	 printf("\r\n");
+#endif
+    
+    for ( int i = 0 ; i < discoverService_count ; i++ ) {
+    	UUID sUUID, cUUID;
+    	if (discoverServiceArr[i].getUUID().shortOrLong() == UUID::UUID_TYPE_SHORT) {
+        	sUUID = UUID(discoverServiceArr[i].getUUID().getShortUUID());
+    	} else {
+    		const uint8_t *longUUIDBytes = discoverServiceArr[i].getUUID().getBaseUUID();
+    		sUUID = UUID(longUUIDBytes);
+        }
+        if ((sUUID == buf_ser_uuid) & (readmatchFlag == false)) {
+        	for (int j = 0 ; j < CLI_CHAR_MAX_NUM ; j++ ) {
+        		if (discoverCharArr[i][j].getUUID().shortOrLong() == UUID::UUID_TYPE_SHORT) {
+        			cUUID = UUID(discoverCharArr[i][j].getUUID().getShortUUID());
+    			} else {
+    				const uint8_t *longUUIDBytes = discoverCharArr[i][j].getUUID().getBaseUUID();
+    				cUUID = UUID(longUUIDBytes);
+    			}
+    			if ((cUUID == buf_char_uuid) & (readmatchFlag == false)) {
+    				printf("OK;");
+	 				for (int i=0 ; i < valueLen; i++) {
+					printf("%02X",bufVal[i]);
+	 				}
+	 				printf("\r\n");
+    				deltaBLE.gattClient().write(GattClient::GATT_OP_WRITE_REQ, discoverCharArr[i][j].getConnectionHandle(), discoverCharArr[i][j].getValueHandle(), valueLen, bufVal);
+    				readmatchFlag = true;
+                    return;
+    			}
+        	}
+        }
+    }
+    	
+    // no matched case, can not read
+    if (readmatchFlag == false) {
+        cyntecPrintError(CYNTEC_CMD_ERR_NO_MATCHED_ARGUMENT);
+    }
+}
+
+static void cynBLECenEnNotifyCommand(void)
+{
+	if (cyntecGetCommandTokenCnt() != 4) {
+        cyntecPrintError(CYNTEC_CMD_ERR_WRONG_NUMBER_OF_ARGUMENTS);
+        return;
+    }
+    UUID buf_ser_uuid ;
+    uint8_t bufferUuidVs[16];
+    UUID buf_char_uuid;
+    bool readmatchFlag = false;
+    uint8_t argLen = 0;
+    uint8_t *arg = cyntecGetCommandArgument(0,&argLen);
+
+    // Handle input parameter - Service UUID
+    if ( argLen == 6 && arg[0] == '0' && arg[1] == 'x') {
+        buf_ser_uuid = cyntecArgToUint16( (arg + 2), (argLen - 2));
+    }
+    if ( argLen == 34 && arg[0] == '0' && arg[1] == 'x' ) {
+        for (uint8_t i=0; i<16; i++) {
+            bufferUuidVs[i] = cyntecArgToUint8( (arg + 2+2*i), 2);
+        }
+        buf_ser_uuid.setupLong(bufferUuidVs);
+    }
+
+    // Handle input parameter -  Characteristic UUID
+    argLen = 0;
+    arg = cyntecGetCommandArgument(1,&argLen);
+    if ( argLen == 6 && arg[0] == '0' && arg[1] == 'x') {
+        buf_char_uuid  = cyntecArgToUint16( (arg + 2), (argLen - 2));
+    }
+    if ( argLen == 34 && arg[0] == '0' && arg[1] == 'x' ) {
+        for (uint8_t i=0; i<16; i++) {
+            bufferUuidVs[i] = cyntecArgToUint8( (arg + 2+2*i), 2);
+        }
+        buf_char_uuid.setupLong(bufferUuidVs);
+    }
+    
+    for ( int i = 0 ; i < discoverService_count ; i++ ) {
+    	UUID sUUID, cUUID;
+    	if (discoverServiceArr[i].getUUID().shortOrLong() == UUID::UUID_TYPE_SHORT) {
+        	sUUID = UUID(discoverServiceArr[i].getUUID().getShortUUID());
+    	} else {
+    		const uint8_t *longUUIDBytes = discoverServiceArr[i].getUUID().getBaseUUID();
+    		sUUID = UUID(longUUIDBytes);
+        }
+        if ((sUUID == buf_ser_uuid) & (readmatchFlag == false)) {
+        	for (int j = 0 ; j < CLI_CHAR_MAX_NUM ; j++ ) {
+        		if (discoverCharArr[i][j].getUUID().shortOrLong() == UUID::UUID_TYPE_SHORT) {
+        			cUUID = UUID(discoverCharArr[i][j].getUUID().getShortUUID());
+    			} else {
+    				const uint8_t *longUUIDBytes = discoverCharArr[i][j].getUUID().getBaseUUID();
+    				cUUID = UUID(longUUIDBytes);
+    			}
+    			if ((cUUID == buf_char_uuid) & (readmatchFlag == false)) {
+    				cyntecPrintOk();
+    				uint16_t value = BLE_HVX_NOTIFICATION;
+    				deltaBLE.gattClient().write(GattClient::GATT_OP_WRITE_REQ, discoverCharArr[i][j].getConnectionHandle(), discoverCharArr[i][j].getValueHandle() + 1, 2, (uint8_t *)&value);
+    				readmatchFlag = true;
+                    return;
+    			}
+        	}
+        }
+    }
+    	
+    // no matched case, can not read
+    if (readmatchFlag == false) {
+        cyntecPrintError(CYNTEC_CMD_ERR_NO_MATCHED_ARGUMENT);
+    }	
+}
+
+static void cynBLECenDisNotifyCommand(void) {
+	if (cyntecGetCommandTokenCnt() != 4) {
+        cyntecPrintError(CYNTEC_CMD_ERR_WRONG_NUMBER_OF_ARGUMENTS);
+        return;
+    }
+    UUID buf_ser_uuid ;
+    uint8_t bufferUuidVs[16];
+    UUID buf_char_uuid;
+    bool readmatchFlag = false;
+    uint8_t argLen = 0;
+    uint8_t *arg = cyntecGetCommandArgument(0,&argLen);
+
+    // Handle input parameter - Service UUID
+    if ( argLen == 6 && arg[0] == '0' && arg[1] == 'x') {
+        buf_ser_uuid = cyntecArgToUint16( (arg + 2), (argLen - 2));
+    }
+    if ( argLen == 34 && arg[0] == '0' && arg[1] == 'x' ) {
+        for (uint8_t i=0; i<16; i++) {
+            bufferUuidVs[i] = cyntecArgToUint8( (arg + 2+2*i), 2);
+        }
+        buf_ser_uuid.setupLong(bufferUuidVs);
+    }
+
+    // Handle input parameter -  Characteristic UUID
+    argLen = 0;
+    arg = cyntecGetCommandArgument(1,&argLen);
+    if ( argLen == 6 && arg[0] == '0' && arg[1] == 'x') {
+        buf_char_uuid  = cyntecArgToUint16( (arg + 2), (argLen - 2));
+    }
+    if ( argLen == 34 && arg[0] == '0' && arg[1] == 'x' ) {
+        for (uint8_t i=0; i<16; i++) {
+            bufferUuidVs[i] = cyntecArgToUint8( (arg + 2+2*i), 2);
+        }
+        buf_char_uuid.setupLong(bufferUuidVs);
+    }
+    
+    for ( int i = 0 ; i < discoverService_count ; i++ ) {
+    	UUID sUUID, cUUID;
+    	if (discoverServiceArr[i].getUUID().shortOrLong() == UUID::UUID_TYPE_SHORT) {
+        	sUUID = UUID(discoverServiceArr[i].getUUID().getShortUUID());
+    	} else {
+    		const uint8_t *longUUIDBytes = discoverServiceArr[i].getUUID().getBaseUUID();
+    		sUUID = UUID(longUUIDBytes);
+        }
+        if ((sUUID == buf_ser_uuid) & (readmatchFlag == false)) {
+        	for (int j = 0 ; j < CLI_CHAR_MAX_NUM ; j++ ) {
+        		if (discoverCharArr[i][j].getUUID().shortOrLong() == UUID::UUID_TYPE_SHORT) {
+        			cUUID = UUID(discoverCharArr[i][j].getUUID().getShortUUID());
+    			} else {
+    				const uint8_t *longUUIDBytes = discoverCharArr[i][j].getUUID().getBaseUUID();
+    				cUUID = UUID(longUUIDBytes);
+    			}
+    			if ((cUUID == buf_char_uuid) & (readmatchFlag == false)) {
+    				cyntecPrintOk();
+    				uint16_t value = 0x00;
+    				deltaBLE.gattClient().write(GattClient::GATT_OP_WRITE_REQ, discoverCharArr[i][j].getConnectionHandle(), discoverCharArr[i][j].getValueHandle() + 1, 2, (uint8_t *)&value);
+    				readmatchFlag = true;
+                    return;
+    			}
+        	}
+        }
+    }
+    	
+    // no matched case, can not read
+    if (readmatchFlag == false) {
+        cyntecPrintError(CYNTEC_CMD_ERR_NO_MATCHED_ARGUMENT);
+    }
+}
+//Silvia modify
+
 static void cynBLEDataIntCommand(void)
 {
     cyntecPrintOk();
@@ -1139,24 +1543,30 @@
     {"GIO", cynBLEGPIOCommand, NULL, "Config gpio, Usage: <GPIO NO> <set|clear>"},
     {"SLP", cynBLESystemOffCommand, NULL, "System off mode, Usage: <GPIO NO>"},
     {"RST", cynResetCommand, NULL, "Soft reset"},
-    {"INF", cynBLEInfoCommand, NULL, "Module information"},
-    {"POW", cynBLESetTxPowerCommand, NULL, "Set BLE tx power, Usage: <POW setting>"},
-    {"NAM", cynBLENameCommand, NULL, "Set/Get friendly for BLE module, Usage: <name>"},
+    {"INF", cynBLEInfoCommand, NULL, "Get module information"},
+    {"POW", cynBLESetTxPowerCommand, NULL, "Set BLE tx power, Usage: <TX POWER>"},
+    {"NAM", cynBLENameCommand, NULL, "Set/Get friendly for BLE module, Usage: <LENGTH> <NAME>"},
 // GATT
     {"GRS", cynRegServiceCommand, NULL, "Register standby service"},
-    {"GAC", cynGattCharCommand, NULL, "Set SIG defined characteristic or Create your own"},
-    {"GAS", cynGattServiceCommand, NULL, "Set SIG defined service or Create your own"},
-    {"ADS", cynAdvertiseStartCommand, NULL, "Start broadcast advertise packet"},
+    {"GAC", cynGattCharCommand, NULL, "Set SIG defined characteristic or Create your own,Usage: <CHAR UUID> <PROPS> <VALUE>"},
+    {"GAS", cynGattServiceCommand, NULL, "Set SIG defined service or Create your own,Usage: <SERVICE UUID>"},
+    {"ADS", cynAdvertiseStartCommand, NULL, "Start broadcast advertise packet,Usage: <INTERVAL> <WINDOW>"},
     {"ADP", cynAdvertiseStopCommand, NULL, "Stop broadcast advertise packet"},
-    {"SCS", cynBLEScanCommand, NULL, "Start to scan BLE device"},
+    {"SCS", cynBLEScanCommand, NULL, "Start to scan BLE device, Usage: <INTERVAL> <WINDOW> <TIMEOUT>"},
     {"SCP", cynBLEScanStopCommand, NULL, "Stop to scan BLE device"},
-    {"CON", cynBLEConnectCommand, NULL, "Connect to specific BLE device by Device Name"},
-    {"DCN", cynBLEDisconnectCommand, NULL, "Disconnection, Usage: cynb disconn"},
-    {"ADR", cynBLEAddressCommand, NULL, "Set/Get Bluetooth address"},
-    {"WRT", cynBLEUpdateDataCommand, NULL, "Update value of specific characteristics"},
-    {"RED", cynBLEReadDataCommand, NULL, "Read value of specific characteristics"},
+    {"CON", cynBLEConnectCommand, NULL, "Connect to specific BLE device by Device Address, Usage: <ADDR>"},
+    {"DCN", cynBLEDisconnectCommand, NULL, "Disconnection"},
+    {"ADR", cynBLEAddressCommand, NULL, "Set/Get Bluetooth address, Usage: <ADDR>"},
+    {"WRT", cynBLEUpdateDataCommand, NULL, "Update value of specific characteristics, Usage: <SERVICE UUID> <CHAR UUID> <TYPE> <VALUE>"},
+    {"RED", cynBLEReadDataCommand, NULL, "Read value of specific characteristics, Usage: <SERVICE UUID> <CHAR UUID>"},
     {"EDI", cynBLEDataIntCommand, NULL, "Trigger remote write detection, give interrupt to Host."},
     {"DDI", cynBLEDisDataIntCommand, NULL, "Disable remote write detection."},
+    //Silvia add BLE central commands
+    {"CIN", cynBLECenInitCommand, NULL, "Init BLE Central stack"},
+    {"CRD", cynBLECenReadDataCommand, NULL, "BLE Central read value of specific characteristics, Usage: <SERVICE UUID> <CHAR UUID>"},
+    {"CWD", cynBLECenWriteDataCommand, NULL, "BLE Central write value to specific characteristics, Usage: <SERVICE UUID> <CHAR UUID> <TYPE> <VALUE>"},
+    {"CEN", cynBLECenEnNotifyCommand, NULL, "BLE Central enable notification of specific characteristics, Usage: <SERVICE UUID> <CHAR UUID>"},
+    {"CDN", cynBLECenDisNotifyCommand, NULL, "BLE Central disable notification of specific characteristics, Usage: <SERVICE UUID> <CHAR UUID>"},
     {NULL, NULL, NULL, NULL},
 #else
     {"init", cynBLEInitCommand, NULL, "Init BLE stack"},
@@ -1164,23 +1574,29 @@
     {"sleep", cynBLESystemOffCommand, NULL, "System off mode, Usage: <GPIO NO>"},
     {"reset", cynResetCommand, NULL, "Soft reset"},
     {"info", cynBLEInfoCommand, NULL, "Get module information"},
-    {"txPow", cynBLESetTxPowerCommand, NULL, "Set BLE tx power, Usage: <POWER>"},
-    {"name", cynBLENameCommand, NULL, "Set/Get friendly for BLE module, Usage: *<NAME>*"},
+    {"txPow", cynBLESetTxPowerCommand, NULL, "Set BLE tx power, Usage: <TX POWER>"},
+    {"name", cynBLENameCommand, NULL, "Set/Get friendly for BLE module, Usage: <LENGTH> <NAME>"},
 // GATT
     {"regService", cynRegServiceCommand, NULL, "Register standby service"},
     {"gattChar", cynGattCharCommand, NULL, "Set SIG defined characteristic or Create your own,Usage: <CHAR UUID> <PROPS> <VALUE>"},
     {"gattService", cynGattServiceCommand, NULL, "Set SIG defined service or Create your own,Usage: <SERVICE UUID>"},
     {"advStart", cynAdvertiseStartCommand, NULL, "Start broadcast advertise packet,Usage: <INTERVAL> <WINDOW>"},
     {"advStop", cynAdvertiseStopCommand, NULL, "Stop broadcast advertise packet"},
-    {"scanStart", cynBLEScanCommand, NULL, "Start to scan BLE device, Usage: <INTERVAL> <WINDOW> <TIMEOUT>"},
-    {"scanStop", cynBLEScanStopCommand, NULL, "Stop to scan BLE device"},
-    {"connect", cynBLEConnectCommand, NULL, "Connect to specific BLE device by Device Name, Usage: <NAME>"},
+    {"scanStart", cynBLEScanCommand, NULL, "Start to scan BLE device, Usage: <INTERVAL> <WINDOW> <TIMEOUT>"}, //BLE central
+    {"scanStop", cynBLEScanStopCommand, NULL, "Stop to scan BLE device"}, //BLE central
+    {"connect", cynBLEConnectCommand, NULL, "Connect to specific BLE device by Device Address, Usage: <ADDR>"}, //Silvia modify, BLE central
     {"disconn", cynBLEDisconnectCommand, NULL, "Disconnection, Usage: cynb disconn"},
     {"bleAddr", cynBLEAddressCommand, NULL, "Set/Get Bluetooth address, Usage: <ADDR>"},
-    {"update", cynBLEUpdateDataCommand, NULL, "Update value of specific characteristics, Usage: <UUID> <VALUE>"},
+    {"update", cynBLEUpdateDataCommand, NULL, "Update value of specific characteristics, Usage: <SERVICE UUID> <CHAR UUID> <TYPE> <VALUE>"},
     {"readData", cynBLEReadDataCommand, NULL, "Read value of specific characteristics, Usage: <SERVICE UUID> <CHAR UUID>"},
     {"enInt", cynBLEDataIntCommand, NULL, "Trigger remote write detection, give interrupt to Host."},
     {"disInt", cynBLEDisDataIntCommand, NULL, "Disable remote write detection."},
+    //Silvia add BLE central commands
+    {"initBleCen", cynBLECenInitCommand, NULL, "Init BLE Central stack"},
+    {"cenReadData", cynBLECenReadDataCommand, NULL, "BLE Central read value of specific characteristics, Usage: <SERVICE UUID> <CHAR UUID>"},
+    {"cenWriteData", cynBLECenWriteDataCommand, NULL, "BLE Central write value to specific characteristics, Usage: <SERVICE UUID> <CHAR UUID> <TYPE> <VALUE>"},
+    {"cenEnNotify", cynBLECenEnNotifyCommand, NULL, "BLE Central enable notification of specific characteristics, Usage: <SERVICE UUID> <CHAR UUID>"},
+    {"cenDisNotify", cynBLECenDisNotifyCommand, NULL, "BLE Central disable notification of specific characteristics, Usage: <SERVICE UUID> <CHAR UUID>"},
     {NULL, NULL, NULL, NULL},
 #endif
 };