Procházet zdrojové kódy

[BC28] optimize bc28 class functions

luhuadong před 5 roky
rodič
revize
20f269fc7a
3 změnil soubory, kde provedl 383 přidání a 213 odebrání
  1. 21 7
      class/bc28/at_device_bc28.c
  2. 4 0
      class/bc28/at_device_bc28.h
  3. 358 206
      class/bc28/at_socket_bc28.c

+ 21 - 7
class/bc28/at_device_bc28.c

@@ -66,6 +66,7 @@ static int bc28_check_link_status(struct at_device *device)
     int result = -RT_ERROR;
     
     bc28 = (struct at_device_bc28 *)device->user_data;
+
     if ( ! bc28->power_status) // power off
     {
         LOG_E("the power is off.");
@@ -181,7 +182,6 @@ static int bc28_netdev_set_info(struct netdev *netdev)
 
     /* set network interface device IP address */
     {
-        #define IP_ADDR_SIZE_MAX    16
         char ipaddr[IP_ADDR_SIZE_MAX] = {0};
         
         /* send "AT+CGPADDR" commond to get IP address */
@@ -376,9 +376,7 @@ static int bc28_netdev_set_dns_server(struct netdev *netdev, uint8_t dns_num, ip
         goto __exit;
     }
 
-    /* send "AT+QIDNSCFG=<pri_dns>[,<sec_dns>]" commond to set dns servers */
-    if (at_obj_exec_cmd(device->client, resp, "AT+QIDNSCFG=%d,%s", 
-        dns_num, inet_ntoa(*dns_server)) != RT_EOK)
+    if (at_obj_exec_cmd(device->client, resp, "AT+QIDNSCFG=%s", inet_ntoa(*dns_server)) != RT_EOK)
     {
         result = -RT_ERROR;
         goto __exit;
@@ -439,7 +437,11 @@ static int bc28_netdev_ping(struct netdev *netdev, const char *host,
 #ifdef AT_USING_SOCKET
     else
     {
-        bc28_domain_resolve(host, ip_addr);
+        if(0 > bc28_domain_resolve(host, ip_addr))
+        {
+            LOG_E("can not resolve domain");
+            goto __exit;
+        }
     }
 #endif
     
@@ -765,7 +767,6 @@ static void bc28_init_thread_entry(void *parameter)
             rt_thread_mdelay(1000);
             if (at_obj_exec_cmd(device->client, resp, "AT+CGPADDR") == RT_EOK)
             {
-                #define IP_ADDR_SIZE_MAX    16
                 char ipaddr[IP_ADDR_SIZE_MAX] = {0};
                 
                 /* parse response data "+CGPADDR: 0,<IP_address>" */
@@ -849,6 +850,19 @@ static int bc28_init(struct at_device *device)
 {
     struct at_device_bc28 *bc28 = (struct at_device_bc28 *)device->user_data;
 
+    /* configure AT client */
+    rt_device_t serial = rt_device_find(bc28->client_name);
+    struct serial_configure config = RT_SERIAL_CONFIG_DEFAULT;
+
+    config.baud_rate = BC28_AT_CLIENT_BAUD_RATE;
+    config.data_bits = DATA_BITS_8;
+    config.stop_bits = STOP_BITS_1;
+    config.bufsz     = bc28->recv_bufsz;
+    config.parity    = PARITY_NONE;
+
+    rt_device_control(serial, RT_DEVICE_CTRL_CONFIG, &config);
+    rt_device_close(serial);
+
     /* initialize AT client */
     at_client_init(bc28->client_name, bc28->recv_bufsz);
 
@@ -950,4 +964,4 @@ static int bc28_device_class_register(void)
 }
 INIT_DEVICE_EXPORT(bc28_device_class_register);
 
-#endif /* AT_DEVICE_USING_BC28 */
+#endif /* AT_DEVICE_USING_BC28 */

+ 4 - 0
class/bc28/at_device_bc28.h

@@ -35,6 +35,10 @@ extern "C" {
 
 /* The maximum number of sockets supported by the BC28 device */
 #define AT_DEVICE_BC28_SOCKETS_NUM  7
+#define IP_ADDR_SIZE_MAX            16
+
+#define AT_DEVICE_BC28_MIN_SOCKET   BC28_SAMPLE_MIN_SOCKET
+#define BC28_AT_CLIENT_BAUD_RATE    BC28_SAMPLE_BAUD_RATE
 
 struct at_device_bc28
 {

+ 358 - 206
class/bc28/at_socket_bc28.c

@@ -32,7 +32,8 @@
 
 #if defined(AT_DEVICE_USING_BC28) && defined(AT_USING_SOCKET)
 
-#define BC28_MODULE_SEND_MAX_SIZE       1024
+#define BC28_MODULE_SEND_MAX_SIZE       1358
+#define BC28_MODULE_RECV_MAX_SIZE       1358
 
 /* set real event by current socket and current state */
 #define SET_EVENT(socket, event)       (((socket + 1) << 16) | (event))
@@ -45,12 +46,86 @@
 #define BC28_EVENT_CONN_FAIL           (1L << 4)
 #define BC28_EVENT_SEND_FAIL           (1L << 5)
 #define BC28_EVENT_DOMAIN_OK           (1L << 6)
+#define BC28_EVENT_DOMAIN_FAIL         (1L << 7)
 
 static at_evt_cb_t at_evt_cb_set[] = {
-        [AT_SOCKET_EVT_RECV] = NULL,
+
+        [AT_SOCKET_EVT_RECV]   = NULL,
         [AT_SOCKET_EVT_CLOSED] = NULL,
 };
 
+static struct at_socket_ip_info
+{
+    char ip_addr[IP_ADDR_SIZE_MAX];
+    int  port;
+} bc28_sock_info[AT_DEVICE_BC28_SOCKETS_NUM];
+
+/**
+ * convert data from ASCII string to Hex string.
+ *
+ * @param str  input ASCII string
+ * @param hex  output Hex string
+ * @param len  length of str, or the size you want to convert
+ *
+ * @return =0: convert failed, or no data need to convert
+ *         >0: the size of convert success
+ */
+static int string_to_hex(const char *str, char *hex, const rt_size_t len)
+{
+    RT_ASSERT(str && hex);
+
+    int str_len = rt_strlen(str);
+    int pos = 0, i;
+
+    if (len < 1 || str_len < len)
+    {
+        return 0;
+    }
+
+    for (i = 0; i < len; i++, pos += 2)
+    {
+        rt_sprintf(&hex[pos], "%02X", str[i]);
+    }
+
+    return i;
+}
+
+/**
+ * convert data from Hex string to ASCII string.
+ *
+ * @param hex  input Hex string
+ * @param str  output ASCII string
+ * @param len  length of str, or the size you want to convert
+ *
+ * @return =0: convert failed, or no data need to convert
+ *         >0: the size of convert success
+ */
+static int hex_to_string(const char *hex, char *str, const rt_size_t len)
+{
+    RT_ASSERT(hex && str);
+
+    int hex_len = rt_strlen(hex);
+    int pos = 0, left, right, i;
+
+    if (len < 1 || hex_len/2 < len)
+    {
+        return 0;
+    }
+
+    for (i = 0; i < len*2; i++, pos++)
+    {
+        left = hex[i++];
+        right = hex[i];
+
+        left  = (left  < 58) ? (left  - 48) : (left  - 55);
+        right = (right < 58) ? (right - 48) : (right - 55);
+
+        str[pos] = (left << 4) | right;
+    }
+
+    return pos;
+}
+
 static void at_tcp_ip_errcode_parse(int result)//TCP/IP_QIGETERROR
 {
     switch(result)
@@ -86,7 +161,6 @@ static void at_tcp_ip_errcode_parse(int result)//TCP/IP_QIGETERROR
     }
 }
 
-
 static int bc28_socket_event_send(struct at_device *device, uint32_t event)
 {
     return (int) rt_event_send(device->socket_event, event);
@@ -120,10 +194,10 @@ static int bc28_socket_close(struct at_socket *socket)
 {
     int result = RT_EOK;
     at_response_t resp = RT_NULL;
-    int device_socket = (int) socket->user_data;
+    int device_socket = (int) socket->user_data + AT_DEVICE_BC28_MIN_SOCKET;
     struct at_device *device = (struct at_device *) socket->device;
 
-    resp = at_create_resp(64, 0, rt_tick_from_millisecond(300));
+    resp = at_create_resp(64, 0, rt_tick_from_millisecond(3000));
     if (resp == RT_NULL)
     {
         LOG_E("no memory for resp create.");
@@ -131,12 +205,87 @@ static int bc28_socket_close(struct at_socket *socket)
     }
     
     result = at_obj_exec_cmd(device->client, resp, "AT+NSOCL=%d", device_socket);
-
+    if (result < 0)
+    {
+        LOG_E("%s device close socket(%d) failed [%d].", device->name, device_socket, result);
+    }
+    else
+    {
+        LOG_D("%s device close socket(%d).", device->name, device_socket);
+    }
+    
     at_delete_resp(resp);
 
     return result;
 }
 
+/**
+ * create socket by AT commands.
+ *
+ * @param type connect socket type(tcp, udp)
+ * @param port listen port (range: 0-65535), if 0 means get a random port
+ *
+ * @return >=0: create socket success, return the socket id (0-6)
+ *          -1: send or exec AT commands error
+ *          -5: no memory
+ */
+static int bc28_socket_create(struct at_device *device, enum at_socket_type type, uint32_t port)
+{
+    const char *type_str = RT_NULL;
+    uint32_t protocol = 0;
+    at_response_t resp = RT_NULL;
+    int socket = -1, result = 0;
+
+    switch(type)
+    {
+        case AT_SOCKET_TCP:
+            type_str = "STREAM";
+            protocol = 6;
+            break;
+        case AT_SOCKET_UDP:
+            type_str = "DGRAM";
+            protocol = 17;
+            break;
+        default:
+            return -RT_ERROR;
+    }
+
+    resp = at_create_resp(128, 0, rt_tick_from_millisecond(300));
+    if (resp == RT_NULL)
+    {
+        LOG_E("no memory for resp create.");
+        return -RT_ENOMEM;
+    }
+
+    /* create socket */
+    if (at_obj_exec_cmd(device->client, resp, "AT+NSOCR=%s,%d,%d,1", type_str, protocol, port) < 0)
+    {
+        result = -RT_ERROR;
+        goto __exit;
+    }
+
+    /* check socket */
+    if (at_resp_parse_line_args(resp, 2, "%d", &socket) <= 0)
+    {
+        LOG_E("%s device create %s socket failed.", device->name, type_str);
+        result = -RT_ERROR;
+        goto __exit;
+    }
+    else
+    {
+        LOG_D("%s device create a %s socket(%d).", device->name, type_str, socket);
+        result = socket;
+    }
+
+__exit:
+    if (resp)
+    {
+        at_delete_resp(resp);
+    }
+
+    return result;
+}
+
 /**
  * create TCP/UDP client or server connect by AT commands.
  *
@@ -152,27 +301,22 @@ static int bc28_socket_close(struct at_socket *socket)
  *          -5: no memory
  */
 static int bc28_socket_connect(struct at_socket *socket, char *ip, int32_t port,
-    enum at_socket_type type, rt_bool_t is_client)
+                               enum at_socket_type type, rt_bool_t is_client)
 {
-#define CONN_RETRY  2
+#define CONN_RETRY  3
 
     int i = 0;
-    const char *type_str = RT_NULL;
     uint32_t event = 0;
     at_response_t resp = RT_NULL;
     int result = 0, event_result = 0;
-    int device_socket = (int) socket->user_data;
+    int device_socket = (int) socket->user_data + AT_DEVICE_BC28_MIN_SOCKET;
+    int return_socket = -1;
     struct at_device *device = (struct at_device *) socket->device;
 
     RT_ASSERT(ip);
     RT_ASSERT(port >= 0);
 
-    if ( ! is_client)
-    {
-        return -RT_ERROR;
-    }
-
-    if (type != AT_SOCKET_TCP)
+    if (!is_client)
     {
         return -RT_ERROR;
     }
@@ -184,90 +328,86 @@ static int bc28_socket_connect(struct at_socket *socket, char *ip, int32_t port,
         return -RT_ENOMEM;
     }
 
+    return_socket = bc28_socket_create(device, type, 0);
+
+    if (return_socket != device_socket)
+    {
+        LOG_E("socket not match (request %d, return %d).", device_socket, return_socket);
+
+        result = at_obj_exec_cmd(device->client, resp, "AT+NSOCL=%d", return_socket);
+        if (result < 0)
+        {
+            LOG_E("%s device close socket(%d) failed [%d].", device->name, return_socket, result);
+        }
+        else
+        {
+            LOG_D("%s device close socket(%d).", device->name, return_socket);
+
+            /* notice the socket is disconnect by remote */
+            if (at_evt_cb_set[AT_SOCKET_EVT_CLOSED])
+            {
+                at_evt_cb_set[AT_SOCKET_EVT_CLOSED](socket, AT_SOCKET_EVT_CLOSED, NULL, 0);
+            }
+        }
+        
+        result = -RT_ERROR;
+        goto __exit;
+    }
+
+    /* if the protocol is not tcp, no need connect to server */
+    if (type != AT_SOCKET_TCP)
+    {
+        if (type == AT_SOCKET_UDP)
+        {
+            rt_strncpy(bc28_sock_info[device_socket].ip_addr, ip, IP_ADDR_SIZE_MAX);
+            bc28_sock_info[device_socket].port = port;
+        }
+        return RT_EOK;
+    }
+
     for(i=0; i<CONN_RETRY; i++)
     {
         /* clear socket connect event */
         event = SET_EVENT(device_socket, BC28_EVENT_CONN_OK | BC28_EVENT_CONN_FAIL);
         bc28_socket_event_recv(device, event, 0, RT_EVENT_FLAG_OR);
 
-        if (at_obj_exec_cmd(device->client, resp, "AT+NSOCO=%d,%s,%d", 
-                            device_socket, ip, port) < 0)
+        if (at_obj_exec_cmd(device->client, resp, "AT+NSOCO=%d,%s,%d", device_socket, ip, port) < 0)
         {
             result = -RT_ERROR;
-            break;
+            continue;
         }
+        LOG_D("%s device socket(%d) try connect to %s:%d.", device->name, device_socket, ip, port);
 
-        /* waiting result event from AT URC, the device default connection timeout is 60 seconds*/
+        if(!at_resp_get_line_by_kw(resp, "OK"))
+        {
+            result = -RT_ERROR;
+            continue;
+        }
+
+        /* waiting result event from AT URC, the device default connection timeout is 30 seconds*/
         if (bc28_socket_event_recv(device, SET_EVENT(device_socket, 0), 
-                                    60 * RT_TICK_PER_SECOND, RT_EVENT_FLAG_OR) < 0)
+                                   30 * RT_TICK_PER_SECOND, RT_EVENT_FLAG_OR) < 0)
         {
-            LOG_E("%s device socket(%d) wait connect result timeout.", device->name, device_socket);
-            result = -RT_ETIMEOUT;
+            LOG_D("%s device socket(%d) wait connect result timeout.", device->name, device_socket);
+            /* No news is good news */
+            result = RT_EOK;
             break;
         }
+
         /* waiting OK or failed result */
         event_result = bc28_socket_event_recv(device, BC28_EVENT_CONN_OK | BC28_EVENT_CONN_FAIL, 
-                                                1 * RT_TICK_PER_SECOND, RT_EVENT_FLAG_OR);
-        if (event_result < 0)
+                                              1 * RT_TICK_PER_SECOND, RT_EVENT_FLAG_OR);
+        if (event_result & BC28_EVENT_CONN_FAIL)
         {
-            LOG_E("%s device socket(%d) wait connect OK|FAIL timeout.", device->name, device_socket);
-            result = -RT_ETIMEOUT;
-            break;
+            LOG_E("%s device socket(%d) connect failed.", device->name, device_socket);
+            result = -RT_ERROR;
+            continue;
         }
-        /* check result */
-        if (event_result & BC28_EVENT_CONN_OK)
+        else
         {
             result = RT_EOK;
             break;
         }
-        
-        LOG_D("%s device socket(%d) connect failed, the socket was not be closed and now will connect retry.",
-                    device->name, device_socket);
-        if (bc28_socket_close(socket) < 0)
-        {
-            result = -RT_ERROR;
-            break;
-        }
-    }
-
-    if (i == CONN_RETRY)
-    {
-        LOG_E("%s device socket(%d) connect failed.", device->name, device_socket);
-        result = -RT_ERROR;
-    }
-    
-    if (resp)
-    {
-        at_delete_resp(resp);
-    }
-
-    return result;
-}
-
-static int at_get_send_size(struct at_socket *socket, size_t *size, size_t *acked, size_t *nacked)
-{
-    int result = 0;
-    at_response_t resp = RT_NULL;
-    int device_socket = (int) socket->user_data;
-    struct at_device *device = (struct at_device *) socket->device;
-
-    resp = at_create_resp(128, 0, rt_tick_from_millisecond(300));
-    if (resp == RT_NULL)
-    {
-        LOG_E("no memory for resp create.", device->name);
-        return -RT_ENOMEM;
-    }
-
-    if (at_obj_exec_cmd(device->client, resp, "AT+QISEND=%d,0", device_socket) < 0)
-    {
-        result = -RT_ERROR;
-        goto __exit;
-    }
-
-    if (at_resp_parse_line_args_by_kw(resp, "+QISEND:", "+QISEND: %d,%d,%d", size, acked, nacked) <= 0)
-    {
-        result = -RT_ERROR;
-        goto __exit;
     }
 
 __exit:
@@ -279,26 +419,6 @@ __exit:
     return result;
 }
 
-static int at_wait_send_finish(struct at_socket *socket, size_t settings_size)
-{
-    /* get the timeout by the input data size */
-    rt_tick_t timeout = rt_tick_from_millisecond(settings_size);
-    rt_tick_t last_time = rt_tick_get();
-    size_t size = 0, acked = 0, nacked = 0xFFFF;
-
-    while (rt_tick_get() - last_time <= timeout)
-    {
-        at_get_send_size(socket, &size, &acked, &nacked);
-        if (nacked == 0)
-        {
-            return RT_EOK;
-        }
-        rt_thread_mdelay(100);
-    }
-
-    return -RT_ETIMEOUT;
-}
-
 /**
  * send data to server or client by AT commands.
  *
@@ -312,20 +432,21 @@ static int at_wait_send_finish(struct at_socket *socket, size_t settings_size)
  *          -2: waited socket event timeout
  *          -5: no memory
  */
-static int bc28_socket_send(struct at_socket *socket, const char *buff, size_t bfsz, enum at_socket_type type)
+static int bc28_socket_send(struct at_socket *socket, const char *buff, 
+                            size_t bfsz, enum at_socket_type type)
 {
     uint32_t event = 0;
     int result = 0, event_result = 0;
     size_t cur_pkt_size = 0, sent_size = 0;
     at_response_t resp = RT_NULL;
-    int device_socket = (int) socket->user_data;
+    int device_socket = (int) socket->user_data + AT_DEVICE_BC28_MIN_SOCKET;
     struct at_device *device = (struct at_device *) socket->device;
     struct at_device_bc28 *bc28 = (struct at_device_bc28 *) device->user_data;
     rt_mutex_t lock = device->client->lock;
 
     RT_ASSERT(buff);
 
-    resp = at_create_resp(128, 2, rt_tick_from_millisecond(300));
+    resp = at_create_resp(128, 0, rt_tick_from_millisecond(300));
     if (resp == RT_NULL)
     {
         LOG_E("no memory for resp create.");
@@ -334,15 +455,13 @@ static int bc28_socket_send(struct at_socket *socket, const char *buff, size_t b
 
     rt_mutex_take(lock, RT_WAITING_FOREVER);
 
-    /* set current socket for send URC event */
-    bc28->user_data = (void *) device_socket;
-
     /* clear socket send event */
     event = SET_EVENT(device_socket, BC28_EVENT_SEND_OK | BC28_EVENT_SEND_FAIL);
     bc28_socket_event_recv(device, event, 0, RT_EVENT_FLAG_OR);
 
-    /* set AT client end sign to deal with '>' sign.*/
-    at_obj_set_end_sign(device->client, '>');
+    /* only use for UDP socket */
+    const char *ip = bc28_sock_info[device_socket].ip_addr;
+    const int port = bc28_sock_info[device_socket].port;
 
     while (sent_size < bfsz)
     {
@@ -355,61 +474,95 @@ static int bc28_socket_send(struct at_socket *socket, const char *buff, size_t b
             cur_pkt_size = BC28_MODULE_SEND_MAX_SIZE;
         }
 
-        /* send the "AT+QISEND" commands to AT server than receive the '>' response on the first line. */
-        if (at_obj_exec_cmd(device->client, resp, "AT+QISEND=%d,%d", device_socket, (int)cur_pkt_size) < 0)
+        size_t i = 0, ind = 0;
+        char hex_data[cur_pkt_size * 2 + 1];
+        rt_memset(hex_data, 0, sizeof(hex_data));
+
+        for (i=0, ind=0; i<cur_pkt_size; i++, ind+=2)
+        {
+            sprintf(&hex_data[ind], "%02X", buff[sent_size + i]);
+        }
+
+        switch (type)
         {
+        case AT_SOCKET_TCP:
+            /* AT+NSOSD=<socket>,<length>,<data>[,<flag>[,<sequence>]] */
+            if (at_obj_exec_cmd(device->client, resp, "AT+NSOSD=%d,%d,%s,0x100,1", device_socket, 
+                                (int)cur_pkt_size, hex_data) < 0)
+            {
+                result = -RT_ERROR;
+                goto __exit;
+            }
+            LOG_D("%s device tcp socket(%d) send %d bytes.\n>> %s", device->name, device_socket, (int)cur_pkt_size, hex_data);
+            break;
+
+        case AT_SOCKET_UDP:
+            /* AT+NSOST=<socket>,<remote_addr>,<remote_port>,<length>,<data>[,<sequence>] */
+            if (at_obj_exec_cmd(device->client, resp, "AT+NSOST=%d,%s,%d,%d,%s,1", device_socket, 
+                                ip, port, (int)cur_pkt_size, hex_data) < 0)
+            {
+                result = -RT_ERROR;
+                goto __exit;
+            }
+            LOG_D("%s device udp socket(%d) send %d bytes to %s:%d.\n>> %s", device->name, device_socket, ip, port, (int)cur_pkt_size, hex_data);
+            break;
+        
+        default:
+            LOG_E("not supported send type %d.", type);
             result = -RT_ERROR;
             goto __exit;
         }
-        
-        rt_thread_mdelay(5);//delay at least 4ms
-        
-        /* send the real data to server or client */
-        result = (int) at_client_obj_send(device->client, buff + sent_size, cur_pkt_size);
-        if (result == 0)
+
+        /* check if sent ok */
+        if (!at_resp_get_line_by_kw(resp, "OK"))
         {
+            LOG_E("%s device socket(%d) send data failed.", device->name, device_socket);
             result = -RT_ERROR;
             goto __exit;
         }
 
-        /* waiting result event from AT URC */
-        event = SET_EVENT(device_socket, 0);
-        event_result = bc28_socket_event_recv(device, event, 10 * RT_TICK_PER_SECOND, RT_EVENT_FLAG_OR);
-        if (event_result < 0)
+        int return_socket = -1, return_size = -1;
+
+        if (at_resp_parse_line_args(resp, 2, "%d,%d", &return_socket, &return_size) <= 0)
         {
-            LOG_E("%s device socket(%d) wait event timeout.", device->name, device_socket);
-            result = -RT_ETIMEOUT;
+            LOG_E("%s device socket(%d) send data failed.", device->name, device_socket);
+            result = -RT_ERROR;
             goto __exit;
         }
-        /* waiting OK or failed result */
-        event = BC28_EVENT_SEND_OK | BC28_EVENT_SEND_FAIL;
-        event_result = bc28_socket_event_recv(device, event, 1 * RT_TICK_PER_SECOND, RT_EVENT_FLAG_OR);
-        if (event_result < 0)
+
+        if (return_socket != device_socket || return_size != cur_pkt_size)
         {
-            LOG_E("%s device socket(%d) wait sned OK|FAIL timeout.", device->name, device_socket);
+            LOG_E("%s device socket(%d) send data incompletely.", device->name, device_socket);
+            result = -RT_ERROR;
+            goto __exit;
+        }
+
+        /* waiting result event from AT URC, the device default timeout is 60 seconds*/
+        if (bc28_socket_event_recv(device, SET_EVENT(device_socket, 0), 
+                                   60 * RT_TICK_PER_SECOND, RT_EVENT_FLAG_OR) < 0)
+        {
+            LOG_E("%s device socket(%d) wait send result timeout.", device->name, device_socket);
             result = -RT_ETIMEOUT;
             goto __exit;
         }
-        /* check result */
+        /* waiting OK or failed result */
+        event_result = bc28_socket_event_recv(device, BC28_EVENT_SEND_OK | BC28_EVENT_SEND_FAIL, 
+                                              1 * RT_TICK_PER_SECOND, RT_EVENT_FLAG_OR);
         if (event_result & BC28_EVENT_SEND_FAIL)
         {
             LOG_E("%s device socket(%d) send failed.", device->name, device_socket);
             result = -RT_ERROR;
             goto __exit;
         }
-
-        if (type == AT_SOCKET_TCP)
+        else
         {
-            at_wait_send_finish(socket, 2*cur_pkt_size);
+            LOG_D("%s device socket(%d) send success.", device->name, device_socket);
+            sent_size += cur_pkt_size;
+            result = sent_size;
         }
-
-        sent_size += cur_pkt_size;
     }
 
 __exit:
-    /* reset the end sign for data conflict */
-    at_obj_set_end_sign(device->client, 0);
-
     rt_mutex_release(lock);
 
     if (resp)
@@ -433,9 +586,9 @@ __exit:
  */
 int bc28_domain_resolve(const char *name, char ip[16])
 {
-    #define RESOLVE_RETRY  3
+#define RESOLVE_RETRY  1
 
-    int i, result;
+    int i, result, event_result = 0;
     at_response_t resp = RT_NULL;
     struct at_device *device = RT_NULL;
     struct at_device_bc28 *bc28 = RT_NULL;
@@ -464,7 +617,7 @@ int bc28_domain_resolve(const char *name, char ip[16])
     bc28 = (struct at_device_bc28 *) device->user_data;
     bc28->socket_data = ip;
 
-    if (at_obj_exec_cmd(device->client, resp, "AT+QDNS=0,%s", name) != RT_EOK)
+    if (at_obj_exec_cmd(device->client, resp, "AT+QDNS=0,%s", name) < 0)
     {
         result = -RT_ERROR;
         goto __exit;
@@ -473,25 +626,23 @@ int bc28_domain_resolve(const char *name, char ip[16])
     for(i = 0; i < RESOLVE_RETRY; i++)
     {
         /* waiting result event from AT URC, the device default connection timeout is 30 seconds.*/
-        if (bc28_socket_event_recv(device, BC28_EVENT_DOMAIN_OK, 10 * RT_TICK_PER_SECOND, RT_EVENT_FLAG_OR) < 0)
+        event_result = bc28_socket_event_recv(device, BC28_EVENT_DOMAIN_OK | BC28_EVENT_DOMAIN_FAIL, 
+                                              30 * RT_TICK_PER_SECOND, RT_EVENT_FLAG_OR);
+        if (event_result < 0)
         {
             result = -RT_ETIMEOUT;
             continue;
         }
+        else if (event_result & BC28_EVENT_DOMAIN_FAIL)
+        {
+            LOG_E("%d device resolve domain name failed.", device->name);
+            result = -RT_ERROR;
+            continue;
+        }
         else
         {
-            if (rt_strlen(ip) < 8)
-            {
-                rt_thread_mdelay(100);
-                /* resolve failed, maybe receive an URC CRLF */
-                result = -RT_ERROR;
-                continue;
-            }
-            else
-            {
-                result = RT_EOK;
-                break;
-            }
+            result = RT_EOK;
+            break;
         }
     }
 
@@ -535,7 +686,8 @@ static void urc_connect_func(struct at_client *client, const char *data, rt_size
         return;
     }
 
-    sscanf(data, "+QIOPEN: %d,%d", &device_socket , &result);
+    /* only for firmware version base BC28JAR02xxx */
+    sscanf(data, "+QTCPIND: %d,%d", &device_socket , &result);
 
     if (result == 0)
     {
@@ -550,7 +702,7 @@ static void urc_connect_func(struct at_client *client, const char *data, rt_size
 
 static void urc_send_func(struct at_client *client, const char *data, rt_size_t size)
 {
-    int device_socket = 0;
+    int device_socket = 0, sequence = 0, status = 0;
     struct at_device *device = RT_NULL;
     struct at_device_bc28 *bc28 = RT_NULL;
     char *client_name = client->device->parent.name;
@@ -563,15 +715,14 @@ static void urc_send_func(struct at_client *client, const char *data, rt_size_t
         LOG_E("get device(%s) failed.", client_name);
         return;
     }
-    
-    bc28 = (struct at_device_bc28 *) device->user_data;
-    device_socket = (int) bc28->user_data;
 
-    if (rt_strstr(data, "SEND OK"))
+    sscanf(data, "+NSOSTR:%d,%d,%d", &device_socket, &sequence, &status);
+    
+    if (1 == status)
     {
         bc28_socket_event_send(device, SET_EVENT(device_socket, BC28_EVENT_SEND_OK));
     }
-    else if (rt_strstr(data, "SEND FAIL"))
+    else
     {
         bc28_socket_event_send(device, SET_EVENT(device_socket, BC28_EVENT_SEND_FAIL));
     }
@@ -593,14 +744,20 @@ static void urc_close_func(struct at_client *client, const char *data, rt_size_t
         return;
     }
 
-    sscanf(data, "+QIURC: \"closed\",%d", &device_socket);
-    /* get at socket object by device socket descriptor */
-    socket = &(device->sockets[device_socket]);
+    sscanf(data, "+NSOCLI: %d", &device_socket);
 
-    /* notice the socket is disconnect by remote */
-    if (at_evt_cb_set[AT_SOCKET_EVT_CLOSED])
+    bc28_socket_event_send(device, SET_EVENT(device_socket, BC28_EVENT_CONN_FAIL));
+    
+    if (device_socket - AT_DEVICE_BC28_MIN_SOCKET >= 0)
     {
-        at_evt_cb_set[AT_SOCKET_EVT_CLOSED](socket, AT_SOCKET_EVT_CLOSED, NULL, 0);
+        /* get at socket object by device socket descriptor */
+        socket = &(device->sockets[device_socket - AT_DEVICE_BC28_MIN_SOCKET]);
+
+        /* notice the socket is disconnect by remote */
+        if (at_evt_cb_set[AT_SOCKET_EVT_CLOSED])
+        {
+            at_evt_cb_set[AT_SOCKET_EVT_CLOSED](socket, AT_SOCKET_EVT_CLOSED, NULL, 0);
+        }
     }
 }
 
@@ -609,7 +766,10 @@ static void urc_recv_func(struct at_client *client, const char *data, rt_size_t
     int device_socket = 0;
     rt_int32_t timeout;
     rt_size_t bfsz = 0, temp_size = 0;
-    char *recv_buf = RT_NULL, temp[8] = {0};
+    char *recv_buf = RT_NULL, *hex_buf = RT_NULL, temp[8] = {0};
+    char remote_addr[IP_ADDR_SIZE_MAX] = {0};
+    int remote_port = -1, return_socket = -1, data_length = 0, remaining_length = 0;
+
     struct at_socket *socket = RT_NULL;
     struct at_device *device = RT_NULL;
     char *client_name = client->device->parent.name;
@@ -623,8 +783,14 @@ static void urc_recv_func(struct at_client *client, const char *data, rt_size_t
         return;
     }
 
+    hex_buf = (char *) rt_calloc(1, BC28_MODULE_RECV_MAX_SIZE * 2 + 1);
+
     /* get the current socket and receive buffer size by receive data */
-    sscanf(data, "+QIURC: \"recv\",%d,%d", &device_socket, (int *) &bfsz);
+
+    /* mode 2 => +NSONMI:<socket>,<remote_addr>, <remote_port>,<length>,<data> */
+    sscanf(data, "+NSONMI:%d,%[0-9.],%d,%d,%s", &device_socket, remote_addr, &remote_port, (int *) &bfsz, hex_buf);
+    LOG_D("%s device socket(%d) recv %d bytes from %s:%d\n>> %s", device_socket, bfsz, remote_addr, remote_port, hex_buf);
+
     /* set receive timeout by receive buffer length, not less than 10 ms */
     timeout = bfsz > 10 ? bfsz : 10;
 
@@ -633,8 +799,9 @@ static void urc_recv_func(struct at_client *client, const char *data, rt_size_t
         return;
     }
 
-    recv_buf = (char *) rt_calloc(1, bfsz);
-    if (recv_buf == RT_NULL)
+    recv_buf = (char *) rt_calloc(1, bfsz + 1);
+
+    if (recv_buf == RT_NULL || hex_buf == RT_NULL)
     {
         LOG_E("no memory for URC receive buffer(%d).", bfsz);
         /* read and clean the coming data */
@@ -650,19 +817,18 @@ static void urc_recv_func(struct at_client *client, const char *data, rt_size_t
             }
             temp_size += sizeof(temp);
         }
-        return;
-    }
 
-    /* sync receive data */
-    if (at_client_obj_recv(client, recv_buf, bfsz, timeout) != bfsz)
-    {
-        LOG_E("%s device receive size(%d) data failed.", device->name, bfsz);
-        rt_free(recv_buf);
+        if (recv_buf) rt_free(recv_buf);
+        if (hex_buf)  rt_free(hex_buf);
         return;
     }
 
+    /* convert receive data */
+    hex_to_string(hex_buf, recv_buf, bfsz);
+    rt_free(hex_buf);
+
     /* get at socket object by device socket descriptor */
-    socket = &(device->sockets[device_socket]);
+    socket = &(device->sockets[device_socket - AT_DEVICE_BC28_MIN_SOCKET]);
 
     /* notice the receive buffer and buffer size */
     if (at_evt_cb_set[AT_SOCKET_EVT_RECV])
@@ -671,7 +837,7 @@ static void urc_recv_func(struct at_client *client, const char *data, rt_size_t
     }
 }
 
-static void urc_dnsqip_func(struct at_client *client, const char *data, rt_size_t size)
+static void urc_dns_func(struct at_client *client, const char *data, rt_size_t size)
 {
     int i = 0, j = 0;
     char recv_ip[16] = {0};
@@ -699,9 +865,15 @@ static void urc_dnsqip_func(struct at_client *client, const char *data, rt_size_
     sscanf(data, "+QDNS:%s", recv_ip);
     recv_ip[15] = '\0';
 
-    rt_memcpy(bc28->socket_data, recv_ip, sizeof(recv_ip));
-
-    bc28_socket_event_send(device, BC28_EVENT_DOMAIN_OK);
+    if (rt_strstr(recv_ip, "FAIL"))
+    {
+        bc28_socket_event_send(device, BC28_EVENT_DOMAIN_FAIL);
+    }
+    else
+    {
+        rt_memcpy(bc28->socket_data, recv_ip, sizeof(recv_ip));
+        bc28_socket_event_send(device, BC28_EVENT_DOMAIN_OK);
+    }
 }
 
 static void urc_func(struct at_client *client, const char *data, rt_size_t size)
@@ -711,33 +883,14 @@ static void urc_func(struct at_client *client, const char *data, rt_size_t size)
     LOG_I("URC data : %.*s", size, data);
 }
 
-static void urc_dns_func(struct at_client *client, const char *data, rt_size_t size)
-{
-    RT_ASSERT(data && size);
-
-    urc_dnsqip_func(client, data, size);
-}
-
-static void urc_qiurc_func(struct at_client *client, const char *data, rt_size_t size)
-{
-    RT_ASSERT(data && size);
-
-    switch(*(data + 9))
-    {
-    case 'c' : urc_close_func(client, data, size); break;//+QIURC: "closed"
-    case 'r' : urc_recv_func(client, data, size); break;//+QIURC: "recv"
-    case 'd' : urc_dnsqip_func(client, data, size); break;//+QIURC: "dnsgip"
-    default  : urc_func(client, data, size);      break;
-    }
-}
-
+/* +NSOSTR:<socket>,<sequence>,<status> */
 static const struct at_urc urc_table[] =
 {
-    {"SEND OK",     "\r\n",                 urc_send_func},
-    {"SEND FAIL",   "\r\n",                 urc_send_func},
-    {"+QIOPEN:",    "\r\n",                 urc_connect_func},
-    {"+QIURC:",     "\r\n",                 urc_qiurc_func},
-    {"+QDNS:",      "\r\n",                 urc_dns_func},
+    {"+QDNS:",      "\r\n",       urc_dns_func},
+    {"+QTCPIND:",   "\r\n",       urc_connect_func},
+    {"+NSOSTR:",    "\r\n",       urc_send_func},
+    {"+NSONMI:",    "\r\n",       urc_recv_func},
+    {"+NSOCLI:",    "\r\n",       urc_close_func},
 };
 
 static const struct at_socket_ops bc28_socket_ops =
@@ -763,11 +916,10 @@ int bc28_socket_class_register(struct at_device_class *class)
 {
     RT_ASSERT(class);
 
-    class->socket_num = AT_DEVICE_BC28_SOCKETS_NUM;
+    class->socket_num = AT_DEVICE_BC28_SOCKETS_NUM - AT_DEVICE_BC28_MIN_SOCKET;
     class->socket_ops = &bc28_socket_ops;
 
     return RT_EOK;
 }
 
 #endif /* AT_DEVICE_USING_BC28 && AT_USING_SOCKET */
-