I am trying to design some test cases to check the LTE stability and performance.
I avoid to use the existing Nordic samples to do this as they are too complicate for the testing purposes.
Here is a test case I've made to test the LTE TCP communication stability. It borrows the idea from the samples of asset_tracker, at_client and tcp. TCP is the prime feature on which TLS, MQTT are based. The test case does the following things:
1) start the LTE modem
2) establish a simple TCP connection to a cloud server
3) periodically (10s) monitor the modem status
4) periodically (10s) send 2 bytes of payload to the server
I want to see how long the connection can last.
To build the code, please replace nrf\samples\nrf9160\asset_tracker\src\main.c with the attached main.c. Then rebuild asset_tracker.
You can see the log in fail1.log attached.
I've run this testing code in a Nordic board (v.07.0) and our own board. Both of them show similar result.
The testing result is inconsistent. Sometime it ran only a few loops (the attached fail1.log is of such kind). Sometime it ran longer. Usually it wouldn't exceed 100 loops. When it started to fail, it was usually stuck at recv() which is used to receive AT commands. recv() has been configured with the non-block mode so supposedly it should always return.
Occasionally, it was stuck at connect() when creating TCP connection at boot up.
My questions:
1) is this a proper test case for testing LTE/network stability?
2) is anything missed in the coding for correctly configuring the modem?
3) does the test result meet your expectation?
4) has Nordic done similar testing?
Best,
Kai
#include <zephyr.h> #include <stdio.h> #include <string.h> #include <gps.h> #include <sensor.h> #include <console.h> #include <nrf_cloud.h> #include <dk_buttons_and_leds.h> #include <lte_lc.h> #include <misc/reboot.h> #include <bsd.h> #include "nrf_socket.h" #include "orientation_detector.h" #include <net/socket.h> #include <sys/time.h> #define TCP_HOST "45.33.53.75" #define TCP_PORT 9090 #define LC_MAX_READ_LENGTH1 128 #define AT_CMD_SIZE1(x) (sizeof(x) - 1) static const char subscribe[] = "AT+CEREG=2"; static const char psm_disable[] = "AT+CPSMS=0"; static const char normal[] = "AT+CFUN=1"; static const char success[] = "OK"; static const char status1[] = "+CEREG: 1"; static const char status2[] = "+CEREG:1"; static const char status3[] = "+CEREG: 5"; static const char status4[] = "+CEREG:5"; static int at_cmd1(int fd, const char *cmd, size_t size) { int len; u8_t buffer[LC_MAX_READ_LENGTH1]; printk("====AT send (%d bytes): %s\n", strlen(cmd), cmd); len = send(fd, cmd, size, 0); if (len != size) { printk("***ERROR: AT send: failed, ret=%d.\n", len); return -1; } for (int i=0; i<50; i++) // wait for 5s { len = recv(fd, buffer, LC_MAX_READ_LENGTH1, MSG_DONTWAIT); if (len > 0) { printk("====AT receive (%d bytes): %s", strlen(buffer), buffer); return 0; } k_sleep(K_MSEC(100)); } printk("**********AT receive ERROR.\n"); return -1; } void main(void) { printk("Application started\n"); int err; int at_socket_fd; u8_t buffer[LC_MAX_READ_LENGTH1]; // create AT socket at_socket_fd = socket(AF_LTE, 0, NPROTO_AT); // start modem at_cmd1(at_socket_fd, subscribe, AT_CMD_SIZE1(subscribe)); at_cmd1(at_socket_fd, psm_disable, AT_CMD_SIZE1(psm_disable)); at_cmd1(at_socket_fd, normal, AT_CMD_SIZE1(normal)); // wait for LET connection ready printk("LTE connecting ...\n"); while (true) { int bytes; bytes = recv(at_socket_fd, buffer, LC_MAX_READ_LENGTH1, 0); if (bytes) { buffer[bytes] = 0; printk("====AT receive (%d bytes): %s", bytes, buffer); if (!memcmp(status1, buffer, AT_CMD_SIZE1(status1)) || !memcmp(status2, buffer, AT_CMD_SIZE1(status2)) || !memcmp(status3, buffer, AT_CMD_SIZE1(status3)) || !memcmp(status4, buffer, AT_CMD_SIZE1(status4))) { break; } } } printk("\nLTE connected\n\n"); // get server IP address struct addrinfo * server_addr; err = getaddrinfo(TCP_HOST, NULL, NULL, &server_addr); if (err != 0) { printk("***ERROR: failed to get server IP address\n"); return 0; } // print server IP address { u8_t * p2 = &(((struct sockaddr_in *)server_addr->ai_addr)->sin_addr.s_addr); printk("server IP addr=%d.%d.%d.%d\n", p2[0], p2[1], p2[2], p2[3]); } // set server TCP listening port ((struct sockaddr_in *)server_addr->ai_addr)->sin_port = htons(TCP_PORT); // create & bind TCP socket int tcp_socket_fd; { tcp_socket_fd = socket(AF_INET, SOCK_STREAM, 0); struct sockaddr_in local_addr; local_addr.sin_family = AF_INET; local_addr.sin_port = htons(0); local_addr.sin_addr.s_addr = 0; err = bind(tcp_socket_fd, (struct sockaddr *)&local_addr, sizeof(local_addr)); if (err != 0) { printk("TCP sokcet bind err: %d\n\r", err); return; } } // connect to server while(1) { printk("\nTCP connect()...\n"); err = connect(tcp_socket_fd, (struct sockaddr *)server_addr->ai_addr, sizeof(struct sockaddr_in)); if (err == 0) { printk("TCP connect() succeeded\n\n"); break; } k_sleep(K_MSEC(1000)); // delay 1s } // check modem status; send TCP data to server int loop = 1; while(1) { // read AT socket to see if there is any data; with non-block mode read while (true) { int bytes; bytes = recv(at_socket_fd, buffer, LC_MAX_READ_LENGTH1, MSG_DONTWAIT ); if (bytes <= 0) break; buffer[bytes] = 0; printk("====AT receive (%d bytes): %s", bytes, buffer); } printk("---------------------------------------- %d\n", loop++); // send AT command to check modem status // at_cmd1(at_socket_fd, "AT%XCBAND", AT_CMD_SIZE1("AT%XCBAND")); at_cmd1(at_socket_fd, "AT+CESQ", AT_CMD_SIZE1("AT+CESQ")); at_cmd1(at_socket_fd, "AT+CEREG?", AT_CMD_SIZE1("AT+CEREG?")); at_cmd1(at_socket_fd, "AT+CGDCONT?", AT_CMD_SIZE1("AT+CGDCONT?")); // send TCP data to server #if 1 static char buf[] = {"a"}; static int len = sizeof(buf); err = send(tcp_socket_fd, buf, len, 0); if (err != len) printk("**********TCP send: error=%d.\n", err); else printk("====TCP send (%d bytes)\n", len); #endif // sleep 10s k_sleep(K_MSEC(10000)); } close(at_socket_fd); return 0; }
***** Booting Zephyr OS v1.13.99-ncs2 ***** Secure Boot: configure flash Secure Boot: SPU: set region 0 as Secure Secure Boot: SPU: set region 1 as Secure Secure Boot: SPU: set region 2 as Secure Secure Boot: SPU: set region 3 as Secure Secure Boot: SPU: set region 4 as Secure Secure Boot: SPU: set region 5 as Secure Secure Boot: SPU: set region 6 as Secure Secure Boot: SPU: set region 7 as Secure Secure Boot: SPU: set Flash region 8 as Non-Secure Secure Boot: SPU: set Flash region 9 as Non-Secure Secure Boot: SPU: set Flash region 10 as Non-Secure Secure Boot: SPU: set Flash region 11 as Non-Secure Secure Boot: SPU: set Flash region 12 as Non-Secure Secure Boot: SPU: set Flash region 13 as Non-Secure Secure Boot: SPU: set Flash region 14 as Non-Secure Secure Boot: SPU: set Flash region 15 as Non-Secure Secure Boot: SPU: set Flash region 16 as Non-Secure Secure Boot: SPU: set Flash region 17 as Non-Secure Secure Boot: SPU: set Flash region 18 as Non-Secure Secure Boot: SPU: set Flash region 19 as Non-Secure Secure Boot: SPU: set Flash region 20 as Non-Secure Secure Boot: SPU: set Flash region 21 as Non-Secure Secure Boot: SPU: set Flash region 22 as Non-Secure Secure Boot: SPU: set Flash region 23 as Non-Secure Secure Boot: SPU: set Flash region 24 as Non-Secure Secure Boot: SPU: set Flash region 25 as Non-Secure Secure Boot: SPU: set Flash region 26 as Non-Secure Secure Boot: SPU: set Flash region 27 as Non-Secure Secure Boot: SPU: set Flash region 28 as Non-Secure Secure Boot: SPU: set Flash region 29 as Non-Secure Secure Boot: SPU: set Flash region 30 as Non-Secure Secure Boot: SPU: set Flash region 31 as Non-Secure Secure Boot: configure SRAM Secure Boot: SPU: set SRAM region 0 as Secure Secure Boot: SPU: set SRAM region 1 as Secure Secure Boot: SPU: set SRAM region 2 as Secure Secure Boot: SPU: set SRAM region 3 as Secure Secure Boot: SPU: set SRAM region 4 as Secure Secure Boot: SPU: set SRAM region 5 as Secure Secure Boot: SPU: set SRAM region 6 as Secure Secure Boot: SPU: set SRAM region 7 as Secure Secure Boot: SPU: set SRAM region 8 as Non-Secure Secure Boot: SPU: set SRAM region 9 as Non-Secure Secure Boot: SPU: set SRAM region 10 as Non-Secure Secure Boot: SPU: set SRAM region 11 as Non-Secure Secure Boot: SPU: set SRAM region 12 as Non-Secure Secure Boot: SPU: set SRAM region 13 as Non-Secure Secure Boot: SPU: set SRAM region 14 as Non-Secure Secure Boot: SPU: set SRAM region 15 as Non-Secure Secure Boot: SPU: set SRAM region 16 as Non-Secure Secure Boot: SPU: set SRAM region 17 as Non-Secure Secure Boot: SPU: set SRAM region 18 as Non-Secure Secure Boot: SPU: set SRAM region 19 as Non-Secure Secure Boot: SPU: set SRAM region 20 as Non-Secure Secure Boot: SPU: set SRAM region 21 as Non-Secure Secure Boot: SPU: set SRAM region 22 as Non-Secure Secure Boot: SPU: set SRAM region 23 as Non-Secure Secure Boot: SPU: set SRAM region 24 as Non-Secure Secure Boot: SPU: set SRAM region 25 as Non-Secure Secure Boot: SPU: set SRAM region 26 as Non-Secure Secure Boot: SPU: set SRAM region 27 as Non-Secure Secure Boot: SPU: set SRAM region 28 as Non-Secure Secure Boot: SPU: set SRAM region 29 as Non-Secure Secure Boot: SPU: set SRAM region 30 as Non-Secure Secure Boot: SPU: set SRAM region 31 as Non-Secure Secure Boot: configure peripherals Secure Boot: MSP_NS 20029828 Secure Boot: prepare to jump to Non-Secure image ***** Booting Zephyr OS v1.13.99-ncs2 ***** Application started ====AT send (10 bytes): AT+CEREG=2 ====AT receive (4 bytes): OK ====AT send (10 bytes): AT+CPSMS=0 ====AT receive (4 bytes): OK ====AT send (9 bytes): AT+CFUN=1 ====AT receive (4 bytes): OK LTE connecting ... ====AT receive (32 bytes): +CEREG: 2,"2005","00803103",7 ====AT receive (32 bytes): +CEREG: 1,"2005","00803103",7 LTE connected server IP addr=45.33.53.75 TCP connect()... TCP connect() succeeded ---------------------------------------- 1 ====AT send (7 bytes): AT+CESQ ====AT receive (33 bytes): +CESQ: 99,99,255,255,255,51 OK ====AT send (9 bytes): AT+CEREG? ====AT receive (37 bytes): +CEREG: 2,1,"2005","00803103",7 OK ====AT send (11 bytes): AT+CGDCONT? ====AT receive (101 bytes): +CGDCONT: 0,"IPV4V6","vzwinternet","100.88.205.249 2600:1010:B007:C50D:0000:0057:158A:9F01",0,0 OK ====TCP send (2 bytes) ---------------------------------------- 2 ====AT send (7 bytes): AT+CESQ ====AT receive (33 bytes): +CESQ: 99,99,255,255,255,51 OK ====AT send (9 bytes): AT+CEREG? ====AT receive (37 bytes): +CEREG: 2,1,"2005","00803103",7 OK ====AT send (11 bytes): AT+CGDCONT? ====AT receive (101 bytes): +CGDCONT: 0,"IPV4V6","vzwinternet","100.88.205.249 2600:1010:B007:C50D:0000:0057:158A:9F01",0,0 OK ====TCP send (2 bytes) ---------------------------------------- 3 ====AT send (7 bytes): AT+CESQ ====AT receive (33 bytes): +CESQ: 99,99,255,255,255,51 OK ====AT send (9 bytes): AT+CEREG? ====AT receive (37 bytes): +CEREG: 2,1,"2005","00803103",7 OK ====AT send (11 bytes): AT+CGDCONT? ====AT receive (101 bytes): +CGDCONT: 0,"IPV4V6","vzwinternet","100.88.205.249 2600:1010:B007:C50D:0000:0057:158A:9F01",0,0 OK ====TCP send (2 bytes) ---------------------------------------- 4 ====AT send (7 bytes): AT+CESQ