This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

How to receive SMS message in standby mode in nRF9160?

I want to wake up nRF9160 by SMS.

What I want to do:

The nRF9160 usually sleeps to reduce power consumption, and only when it receives SMS it wakes up and send some data by UDP or so.

I succeeded in implementing MQTT(+TLS), but have no experience to implement SMS function.

Any advice?

Parents Reply Children
  • Hi, Hakon.

    I managed to receive SMS during eDRX on at_client and LTE Link Monitor.

    AT+CFUN=4
    AT%XBANDLOCK=1,"10000000" // Some carriers don't support SMS during eDRX
    AT+CEDRXS=2,4,"0110" // enable eDRX
    AT%XPTW=4,"0111"
    AT+CNMI=3,2,0,1
    AT%XSYSTEMMODE=1,0,0,0
    AT+CFUN=1
    Wait for a while
    AT+CFUN? // Make sure LTE conection is established
    AT+CEDRXRDP
    AT+CNMI?
    SMS from server
    wait until unsolicited message shows up on LLM
    

    When I implement this code in usual project and check if SMS notification shows up on LTE Link Monitor, I can't receive SMS notification even though I set "AT+CNMI=3,2,0,1." SMS seems to be received, but SMS notification is not generated.

    <main>
    .
    .
    .
    void send_at_commands(void)
    {
    
        char recv_buf[1024 + 1];
    	const char *at_commands[] = { "AT+CEDRXRDP", "AT+CNMI?" };
    
    	int at_socket_fd = socket(AF_LTE, 0, NPROTO_AT);
    
    	if (at_socket_fd < 0) {
    		printk("Socket err: %d, errno: %d\r\n", at_socket_fd, errno);
    	}
    	for (int i = 0; i < ARRAY_SIZE(at_commands); i++) {
            printk("%s\n", at_commands[i]);
    		int bytes_written = send(at_socket_fd, at_commands[i],
    					 strlen(at_commands[i]), 0);
    		if (bytes_written > 0) {
    			int r_bytes = blocking_recv(at_socket_fd, recv_buf, sizeof(recv_buf), MSG_DONTWAIT);
    			if (r_bytes > 0) {
    				printk("%s", recv_buf);
    			}
    		}
    	}
    	printk("Closing socket\n\r");
    	(void)close(at_socket_fd);
    }
    
    void main(void)
    {
    	printk("The AT client program started\n");
    	modem_configure();
        send_at_commands();
    }
    

    <lte_lc.c>
    .
    .
    #if defined(CONFIG_LTE_LOCK_BANDS)
    /* Lock LTE bands 8 (volatile setting) */
    static const char lock_bands[] = "AT%XBANDLOCK=2,\"10000000\"";
    #endif
    /* Request eDRX settings to be used */
    static const char edrx_req[] = "AT+CEDRXS=1,"CONFIG_LTE_EDRX_REQ_ACTT_TYPE",\""CONFIG_LTE_EDRX_REQ_VALUE"\"";
    static const char edrx_ptw[] = "AT%XPTW=4,\"0111\"";
    .
    .
    static int w_lte_lc_init_and_connect(struct device *unused)
    {
    /* ADD HERE */
    	if (at_cmd_write(offline, NULL, 0, NULL) != 0) {
    		return -EIO;
    	}
    
    	if (at_cmd_write("AT+CNMI=3,2,0,1", NULL, 0, NULL) != 0) {
    		return -EIO;
    	}
    /* ADD HERE */
    
    #if defined(CONFIG_LTE_EDRX_REQ)
    	/* Request configured eDRX settings to save power */
    	if (at_cmd_write(edrx_req, NULL, 0, NULL) != 0) {
    		return -EIO;
    	}
    	if (at_cmd_write(edrx_ptw, NULL, 0, NULL) != 0) {
    		return -EIO;
    	}
    #endif
    	if (at_cmd_write(subscribe, NULL, 0, NULL) != 0) {
    		return -EIO;
    	}
    
    #if defined(CONFIG_LTE_LOCK_BANDS)
    	/* Set LTE band lock (volatile setting).
    	 * Has to be done every time before activating the modem.
    	 */
    	if (at_cmd_write(lock_bands, NULL, 0, NULL) != 0) {
    		return -EIO;
    	}
    #endif
    #if defined(CONFIG_LTE_LEGACY_PCO_MODE)
    	if (at_cmd_write(legacy_pco, NULL, 0, NULL) != 0) {
    		return -EIO;
    	}
    	LOG_INF("Using legacy LTE PCO mode...");
    #endif
    #if defined(CONFIG_LTE_PDP_CMD)
    	if (at_cmd_write(cgdcont, NULL, 0, NULL) != 0) {
    		return -EIO;
    	}
    	LOG_INF("PDP Context: %s", cgdcont);
    #endif
    	if (at_cmd_write(network_mode, NULL, 0, NULL) != 0) {
    		return -EIO;
    	}
    
    	k_sem_init(&link, 0, 1);
    
    	at_cmd_set_notification_handler(at_handler);
    
    	if (at_cmd_write(normal, NULL, 0, NULL) != 0) {
    		return -EIO;
    	}
    
    	k_sem_take(&link, K_FOREVER);
    
    	at_cmd_set_notification_handler(NULL);
    
    	return 0;
    }


    *Without SMS notification, AT+CNMI was reset and probably SMS is received. 

    /ncs/nrf/drivers/lte_link_control/lte_lc.c

    In this lte_lc.c, I think at_cmd_set_notification_handler is related to this issue. Can you check this?

    Another question:

    Every time SMS is received, SMS notification is reset and you need to run "AT+CNMI=3,2,0,1" again. Why does this happen? Is this possible to set SMS notification permanently?

  • I'm pretty sure that "at_cmd_set_notification_handler"  causes this issue.

    When I comment out the two lines, SMS notification shows up, but when I don't, it doesn't show up.

    Could you help me fix this issue?

    Thank you so much for helping me a lot!

    <lte_lc.c>
    
    static int w_lte_lc_init_and_connect(struct device *unused)
    {
    .
    .
    .
    	if (at_cmd_write(network_mode, NULL, 0, NULL) != 0) {
    		return -EIO;
    	}
    
    	k_sem_init(&link, 0, 1);
    
    //	at_cmd_set_notification_handler(at_handler);
    
    	if (at_cmd_write(normal, NULL, 0, NULL) != 0) {
    		return -EIO;
    	}
    
    	k_sem_take(&link, K_FOREVER);
    
    //	at_cmd_set_notification_handler(NULL);
    
    	return 0;
    }

  • Hi,

     

    I am sorry for the late reply.

    When registering a request from AT+CNMI, you should use AT+CNMA to ACK the received message.

    If the ACK is not delivered before the timeout, the CNMI is released, as per this specification:

    https://infocenter.nordicsemi.com/topic/ref_at_commands/REF/at_commands/text_mode/cnma_set.html?cp=2_1_8_5_0

     

    I do not see how commenting out the at_cmd_set_notification_handler() should influence this procedure. Could you see if the same behavior is observed if you ACK the SMS using CNMA?

     

    Kind regards,

    Håkon

  • Hi, Hakon. Thank you for your reply!

    So these steps should be correct

    1. run "AT+CNMI=3,2,0,1"
    2. polling for an incoming SMS
    3. send SMS from a server
    4. SMS notification shows up once the SMS is received
    5. run "AT+CNMA" right after the notification
    *If I don't run "AT+CNMA"  when SMS is received, SMS notification is disabled.

    OK, I got this.

    However, when I don't comment out at_cmd_set_notification_handler(), no SMS receiving notification shows up, so MCU doesn't know the timing of sending "AT+CNMA" command. I guess at_cmd_set_notification_handler() needs some fix.

    I will try to find a way of polling an incoming SMS. 

  • I'm searching a way of polling SMS receiving notification, but I found only mqtt_simple sample program which has mqtt-specific polling function.

    How can I poll SMS receiving notification? Do you know any reference? 

    I used blocking_recv function which I found in simple_at and this doesn't work.

Related