GNSS and SMS services

I'm trying to get location information sent with SMS to my phone. I have made sure my SIM card is SMS capable by using sms sample, which managed to send and receive messages and GNSS location services work and find fixes. 

I wanted to use simple example for start when combining the two, so I have just tried to add SMS to  devAcademy Cellular fundamentals lesson 6 exercise 1. When running program it crashes when trying to send the SMS after location fix is made and second LED indicator lights up. 

I'm using thingy:91 with external antenna, in Windows 

 

/*
 * Copyright (c) 2022 Nordic Semiconductor ASA
 *
 * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
 */

#include <stdio.h>
#include <zephyr/kernel.h>

#include <zephyr/logging/log.h>
#include <modem/lte_lc.h>
#include <dk_buttons_and_leds.h>

/* STEP 4 - Include the header file for the GNSS interface */
#include <nrf_modem_gnss.h>

// Include SMS 
#include <modem/sms.h>

/* STEP 5 - Define the PVT data frame variable */
static struct nrf_modem_gnss_pvt_data_frame pvt_data;

/* STEP 12.1 - Declare helper variables to find the TTFF */
static int64_t gnss_start_time;
static bool first_fix = false;

static K_SEM_DEFINE(lte_connected, 0, 1);

LOG_MODULE_REGISTER(Lesson6_Exercise1, LOG_LEVEL_INF);

static void lte_handler(const struct lte_lc_evt *const evt)
{
	switch (evt->type) {
	case LTE_LC_EVT_NW_REG_STATUS:
		if ((evt->nw_reg_status != LTE_LC_NW_REG_REGISTERED_HOME) &&
			(evt->nw_reg_status != LTE_LC_NW_REG_REGISTERED_ROAMING)) {
			break;
		}
		LOG_INF("Network registration status: %s",
				evt->nw_reg_status == LTE_LC_NW_REG_REGISTERED_HOME ?
				"Connected - home network" : "Connected - roaming");
		k_sem_give(&lte_connected);
		break;
	case LTE_LC_EVT_RRC_UPDATE:
		LOG_INF("RRC mode: %s", evt->rrc_mode == LTE_LC_RRC_MODE_CONNECTED ? 
				"Connected" : "Idle");
		break;	
	default:
		break;
	}
}

static void modem_configure(void)
{
	LOG_INF("Connecting to LTE network");

	int err = lte_lc_init_and_connect_async(lte_handler);
	if (err) {
		LOG_ERR("Modem could not be configured, error: %d", err);
		return;
	}
	k_sem_take(&lte_connected, K_FOREVER);
	LOG_INF("Connected to LTE network");
	dk_set_led_on(DK_LED2);
}

/* STEP 6 - Define a function to log fix data in a readable format */
static void print_fix_data(struct nrf_modem_gnss_pvt_data_frame *pvt_data)
{
	LOG_INF("Latitude:       %.06f", pvt_data->latitude);
	LOG_INF("Longitude:      %.06f", pvt_data->longitude);
	LOG_INF("Altitude:       %.01f m", pvt_data->altitude);
	LOG_INF("Time (UTC):     %02u:%02u:%02u.%03u",
	       pvt_data->datetime.hour,
	       pvt_data->datetime.minute,
	       pvt_data->datetime.seconds,
	       pvt_data->datetime.ms);
	// Phone number removed for ticket
	if (sms_send_text("","Fix found")!=0)
		LOG_INF("Failed to SMS fix");
}


static void gnss_event_handler(int event)
{
	int err;

	switch (event) {
	/* STEP 7 - On a PVT event, confirm if PVT data is a valid fix */
	case NRF_MODEM_GNSS_EVT_PVT:
		LOG_INF("Searching...");
		/* STEP 15 - Print satellite information */
		int num_satellites = 0;
		for (int i = 0; i < 12 ; i++) {
			if (pvt_data.sv[i].signal != 0) {
				LOG_INF("sv: %d, cn0: %d", pvt_data.sv[i].sv, pvt_data.sv[i].cn0);
				num_satellites++;
			}	
		} 
		LOG_INF("Number of current satellites: %d", num_satellites);
		err = nrf_modem_gnss_read(&pvt_data, sizeof(pvt_data), NRF_MODEM_GNSS_DATA_PVT);
		if (err) {
			LOG_ERR("nrf_modem_gnss_read failed, err %d", err);
			return;
		}
		if (pvt_data.flags & NRF_MODEM_GNSS_PVT_FLAG_FIX_VALID) {
			dk_set_led_on(DK_LED1);
			print_fix_data(&pvt_data);
			/* STEP 12.3 - Print the time to first fix */
			if (!first_fix) {
				LOG_INF("Time to first fix: %2.1lld s", (k_uptime_get() - gnss_start_time)/1000);
				first_fix = true;
			}
			return;
		}
		break;
	/* STEP 7.2 - Log when the GNSS sleeps and wakes up */
	case NRF_MODEM_GNSS_EVT_PERIODIC_WAKEUP:
		LOG_INF("GNSS has woken up");
		break;
	case NRF_MODEM_GNSS_EVT_SLEEP_AFTER_FIX:
		LOG_INF("GNSS enter sleep after fix");
		break;
	default:
		break;
	}
}

static void sms_callback(struct sms_data *const data, void *context)
{
	if (data == NULL) {
		printk("%s with NULL data\n", __func__);
		return;
	}

	if (data->type == SMS_TYPE_DELIVER) {
		/* When SMS message is received, print information */
		struct sms_deliver_header *header = &data->header.deliver;

		printk("\nSMS received:\n");
		printk("\tTime:   %02d-%02d-%02d %02d:%02d:%02d\n",
			header->time.year,
			header->time.month,
			header->time.day,
			header->time.hour,
			header->time.minute,
			header->time.second);

		printk("\tText:   '%s'\n", data->payload);
		printk("\tLength: %d\n", data->payload_len);

		if (header->app_port.present) {
			printk("\tApplication port addressing scheme: dest_port=%d, src_port=%d\n",
				header->app_port.dest_port,
				header->app_port.src_port);
		}
		if (header->concatenated.present) {
			printk("\tConcatenated short message: ref_number=%d, msg %d/%d\n",
				header->concatenated.ref_number,
				header->concatenated.seq_number,
				header->concatenated.total_msgs);
		}
	} else if (data->type == SMS_TYPE_STATUS_REPORT) {
		printk("SMS status report received\n");
	} else {
		printk("SMS protocol message with unknown type received\n");
	}
}

void main(void)
{

	if (dk_leds_init() != 0) {
		LOG_ERR("Failed to initialize the LEDs Library");
	}

	modem_configure();
	
	/* STEP 8 - Activate modem and deactivate LTE */
	if (lte_lc_func_mode_set(LTE_LC_FUNC_MODE_NORMAL) != 0) {
		LOG_ERR("Failed to activate GNSS functional mode");
		return;
	}	
	
	LOG_INF("Deactivating LTE");
	if (lte_lc_func_mode_set(LTE_LC_FUNC_MODE_DEACTIVATE_LTE) != 0) {
		LOG_ERR("Failed to activate GNSS functional mode");
		return;
	}

	/* STEP 9 - Register the GNSS event handler */
	if (nrf_modem_gnss_event_handler_set(gnss_event_handler) != 0) {
		LOG_ERR("Failed to set GNSS event handler");
		return;
	}

	/* STEP 10 - Set the GNSS fix interval and GNSS fix retry period */
	if (nrf_modem_gnss_fix_interval_set(CONFIG_GNSS_PERIODIC_INTERVAL) != 0) {
		LOG_ERR("Failed to set GNSS fix interval");
		return;
	}

	if (nrf_modem_gnss_fix_retry_set(CONFIG_GNSS_PERIODIC_TIMEOUT) != 0) {
		LOG_ERR("Failed to set GNSS fix retry");
		return;
	}

	/* STEP 11 - Start the GNSS receiver*/
	LOG_INF("Starting GNSS");
	if (nrf_modem_gnss_start() != 0) {
		LOG_ERR("Failed to start GNSS");
		return;
	}	
	int handle = sms_register_listener(sms_callback,NULL);
	/* STEP 12.2 - Log the current system uptime */
	gnss_start_time = k_uptime_get();
}

7282.prj.conf

Parents
  • Hi,

    The problem is this snippet in main():

    LOG_INF("Deactivating LTE");
    if (lte_lc_func_mode_set(LTE_LC_FUNC_MODE_DEACTIVATE_LTE) != 0) {
    	LOG_ERR("Failed to activate GNSS functional mode");
    	return;
    }

    If you remove it, you should be able to send SMSes. However, it might affect the GPS performance. The LTE and GNSS stack uses the same resources, and the GNSS stack is only able to run when the LTE stack is not running. This means that unless you use PSM or eDRX to make the LTE stack sleep, the GNSS stack will not get enough runtime to get a fix.

    Best regards,

    Didrik

Reply
  • Hi,

    The problem is this snippet in main():

    LOG_INF("Deactivating LTE");
    if (lte_lc_func_mode_set(LTE_LC_FUNC_MODE_DEACTIVATE_LTE) != 0) {
    	LOG_ERR("Failed to activate GNSS functional mode");
    	return;
    }

    If you remove it, you should be able to send SMSes. However, it might affect the GPS performance. The LTE and GNSS stack uses the same resources, and the GNSS stack is only able to run when the LTE stack is not running. This means that unless you use PSM or eDRX to make the LTE stack sleep, the GNSS stack will not get enough runtime to get a fix.

    Best regards,

    Didrik

Children
  • After removing suggested snippet and acquiring PSM time, I managed to send SMS message after GNSS location fix. Program still crashes after that. If I want to be able to receive SMS messages aswell, would that be possible on this kind current program or would I need to start from scratch? And are there samples with GNSS and SMS that would be of help in that, I did some searching but couldn't find any?

  • Could you share the logs from the device?

    Please also add CONFIG_RESET_ON_FATAL_ERROR=n and CONFIG_so we can get logs from the crash itself.

    silwyr said:
    nd are there samples with GNSS and SMS that would be of help in that, I did some searching but couldn't find any?

    We don't have any samples using both SMS and GNSS, so you will have to merge the SMS sample and one of the GNSS samples manually (as you are already doing).

    One thing to be aware of, is that the GNSS handler is run in an interrupt context (see https://developer.nordicsemi.com/nRF_Connect_SDK/doc/2.3.0/nrfxlib/nrf_modem/doc/gnss_interface.html#handling-events-and-reading-data-from-gnss), so you shouldn't do too much processing in it.

    What happens if you move the SMS-sending to a workqueue?

  • Please also add CONFIG_RESET_ON_FATAL_ERROR=n and CONFIG_so we can get logs from the crash itself.

    Whatis the second CONFIG option that should be changed?

    I'll try the workqueue and add logs when I manage to get them working or get some logs from the crashes.

    After implementing work queue for sending SMS they are sent.

    For receiving SMSes I'm not so sure what to do, as currently they are received sometimes at near start up of the program and status report for sent message is received. 

    This is the current program file.

    /*
     * Copyright (c) 2022 Nordic Semiconductor ASA
     *
     * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
     */
    
    #include <stdio.h>
    #include <zephyr/kernel.h>
    
    #include <zephyr/logging/log.h>
    #include <modem/lte_lc.h>
    #include <dk_buttons_and_leds.h>
    
    #include <nrf_modem_gnss.h>
    
    // Include SMS 
    #include <modem/sms.h>
    
    static struct nrf_modem_gnss_pvt_data_frame pvt_data;
    
    static int64_t gnss_start_time;
    static bool first_fix = false;
    
    static K_SEM_DEFINE(lte_connected, 0, 1);
    static K_SEM_DEFINE(text_ready, 0, 1);
    
    LOG_MODULE_REGISTER(SMSwithGNSS, LOG_LEVEL_INF);
    static int sms_handle;
    
    #define SMS_STACK_SIZE 1512
    #define SMS_PRIORITY 5
    
    
    K_THREAD_STACK_DEFINE(sms_stack_area, SMS_STACK_SIZE);
    
    struct k_work_q sms_work_q;
    struct sms_info {
        struct k_work work;
    	char number[12]; // 
        double lat;
    	double lon;
    } sms_work_struct;
    
    static void lte_handler(const struct lte_lc_evt *const evt)
    {
    	switch (evt->type) {
    	case LTE_LC_EVT_NW_REG_STATUS:
    		if ((evt->nw_reg_status != LTE_LC_NW_REG_REGISTERED_HOME) &&
    			(evt->nw_reg_status != LTE_LC_NW_REG_REGISTERED_ROAMING)) {
    			break;
    		}
    		LOG_INF("Network registration status: %s",
    				evt->nw_reg_status == LTE_LC_NW_REG_REGISTERED_HOME ?
    				"Connected - home network" : "Connected - roaming");
    		k_sem_give(&lte_connected);
    		break;
    	case LTE_LC_EVT_RRC_UPDATE:
    		LOG_INF("RRC mode: %s", evt->rrc_mode == LTE_LC_RRC_MODE_CONNECTED ? 
    				"Connected" : "Idle");
    		break;	
    	case LTE_LC_EVT_PSM_UPDATE:
    		LOG_INF("PSM parameter update: TAU: %d, Active time: %d",
    			evt->psm_cfg.tau, evt->psm_cfg.active_time);
    		if (evt->psm_cfg.active_time == -1){
    			LOG_ERR("Network rejected PSM parameters. Failed to setup network");
    		}
    		break;
    	case LTE_LC_EVT_EDRX_UPDATE:
    		LOG_INF("eDRX parameter update: eDRX: %f, PTW: %f",
    			evt->edrx_cfg.edrx, evt->edrx_cfg.ptw);
    		break;	
    	default:
    		break;
    	}
    }
    
    static void modem_configure(void)
    {
    	int err;
    	err = lte_lc_psm_req(true);
    	if (err) {
    		LOG_ERR("lte_lc_psm_req, error: %d", err);
    	} 
    	
    	// err = lte_lc_edrx_req(true);
    	// if (err) {
    	// 	LOG_ERR("lte_lc_edrx_req, error: %d", err);
    	// }
    
    	LOG_INF("Connecting to LTE network");
    	err = lte_lc_init_and_connect_async(lte_handler);
    	if (err) {
    		LOG_ERR("Modem could not be configured, error: %d", err);
    		return;
    	}
    	k_sem_take(&lte_connected, K_FOREVER);
    	LOG_INF("Connected to LTE network");
    	dk_set_led_on(DK_LED2);
    }
    
    /* STEP 6 - Define a function to log fix data in a readable format */
    static void print_fix_data(struct nrf_modem_gnss_pvt_data_frame *pvt_data)
    {
    	LOG_INF("Latitude:       %.06f", pvt_data->latitude);
    	LOG_INF("Longitude:      %.06f", pvt_data->longitude);
    	LOG_INF("Altitude:       %.01f m", pvt_data->altitude);
    	LOG_INF("Time (UTC):     %02u:%02u:%02u.%03u",
    	       pvt_data->datetime.hour,
    	       pvt_data->datetime.minute,
    	       pvt_data->datetime.seconds,
    	       pvt_data->datetime.ms);
    	// Text send after fix if it wasn't first
    	if (!first_fix){
    		dk_set_led_off(DK_LED1);
    		dk_set_led_off(DK_LED2);
    		k_msleep(100);
    		// k_sem_give(&text_ready);
    		// k_work_submit(&sms_work_struct.work);
    	}
    }
    
    
    static void gnss_event_handler(int event)
    {
    	int err;
    	switch (event) {
    		
    	case NRF_MODEM_GNSS_EVT_PVT:
    		LOG_INF("Searching...");
    		
    		int num_satellites = 0;
    		for (int i = 0; i < 12 ; i++) {
    			if (pvt_data.sv[i].signal != 0) {
    				LOG_INF("sv: %d, cn0: %d", pvt_data.sv[i].sv, pvt_data.sv[i].cn0);
    				num_satellites++;
    			}	
    		} 
    		
    		err = nrf_modem_gnss_read(&pvt_data, sizeof(pvt_data), NRF_MODEM_GNSS_DATA_PVT);
    		if (err) {
    			LOG_ERR("nrf_modem_gnss_read failed, err %d", err);
    			return;
    		}
    		if (pvt_data.flags & NRF_MODEM_GNSS_PVT_FLAG_FIX_VALID) {
    			dk_set_led_on(DK_LED1);
    			print_fix_data(&pvt_data);
    
    			sms_work_struct.lat=pvt_data.latitude;
    			sms_work_struct.lon=pvt_data.longitude;
            	k_work_submit(&sms_work_struct.work);
    			if (!first_fix) {
    				LOG_INF("Time to first fix: %2.1lld s", (k_uptime_get() - gnss_start_time)/1000);
    				first_fix = true;
    			}
    			
    			return;
    		}
    		if (pvt_data.flags & NRF_MODEM_GNSS_PVT_FLAG_SLEEP_BETWEEN_PVT){
    			LOG_INF("GNSS :  At least one sleep period has passed since the last PVT notification");
    			}
    		if (pvt_data.flags & NRF_MODEM_GNSS_PVT_FLAG_DEADLINE_MISSED){
    			LOG_INF("GNSS  'deadline missed' flag");
    			}
    		else if (pvt_data.flags & NRF_MODEM_GNSS_PVT_FLAG_NOT_ENOUGH_WINDOW_TIME){
    			LOG_INF("Insufficient GNSS time windows");
    			}
    		break;
    	case NRF_MODEM_GNSS_EVT_PERIODIC_WAKEUP:
    		LOG_INF("GNSS has woken up");
    		break;
    	case NRF_MODEM_GNSS_EVT_SLEEP_AFTER_FIX:
    		LOG_INF("GNSS enter sleep after fix");
    		break;
    	default:
    		break;
    	}
    }
    
    static void sms_callback(struct sms_data *const data, void *context)
    {
    	if (data == NULL) {
    		LOG_INF("%s with NULL data\n", __func__);
    		return;
    	}
    
    	if (data->type == SMS_TYPE_DELIVER) {
    		/* When SMS message is received, print information */
    		struct sms_deliver_header *header = &data->header.deliver;
    
    		LOG_INF("SMS received from time:%02d-%02d-%02d %02d:%02d:%02d",
    			header->time.year,
    			header->time.month,
    			header->time.day,
    			header->time.hour,
    			header->time.minute,
    			header->time.second);
    
    		LOG_INF("Text:   '%s'", data->payload);
    		LOG_INF("Length: %d", data->payload_len);
    
    		if (header->app_port.present) {
    			LOG_INF("\tApplication port addressing scheme: dest_port=%d, src_port=%d\n",
    				header->app_port.dest_port,
    				header->app_port.src_port);
    		}
    		if (header->concatenated.present) {
    			LOG_INF("\tConcatenated short message: ref_number=%d, msg %d/%d\n",
    				header->concatenated.ref_number,
    				header->concatenated.seq_number,
    				header->concatenated.total_msgs);
    		}
    	} else if (data->type == SMS_TYPE_STATUS_REPORT) {
    		LOG_INF("SMS status report received");
    	} else {
    		LOG_INF("SMS protocol message with unknown type received");
    	}
    }
    
    static void sms_send(struct k_work *item)
    {
    	LOG_INF("SMS send message work");
        struct sms_info *sms_message =
            CONTAINER_OF(item, struct sms_info, work);
    	char lat[10];
    	char lon[10];
    	char sms_text[160];
    	snprintf(lat,sizeof(lat),"%f",pvt_data.latitude);
    	snprintf(lon,sizeof(lon),"%f",pvt_data.longitude);
    	snprintf(sms_text,sizeof(sms_text),"Fix found at %s, %s",lat,lon);
    		if (sms_send_text(sms_message->number,sms_text)!=0)
    			LOG_INF("Failed to SMS fix");
    	LOG_INF("SMS message '%s' to number '%s'",sms_text,sms_message->number);
    }
    
    void main(void)
    {
    
    	k_work_queue_init(&sms_work_q);
    
    	k_work_queue_start(&sms_work_q, sms_stack_area,
    					K_THREAD_STACK_SIZEOF(sms_stack_area), SMS_PRIORITY,
    					NULL);
    	
    	//Set some beginning coordinates and phone number
    	strcpy(sms_work_struct.number,"+");
    	sms_work_struct.lat=65.014523;
    	sms_work_struct.lon=25.483436;
    
    	k_work_init(&sms_work_struct.work, sms_send);
    
    	if (dk_leds_init() != 0) {
    		LOG_ERR("Failed to initialize the LEDs Library");
    	}
    
    	modem_configure();
    	
    	if (lte_lc_func_mode_set(LTE_LC_FUNC_MODE_NORMAL) != 0) {
    		LOG_ERR("Failed to activate GNSS functional mode");
    		return;
    	}	
    	
    	if (nrf_modem_gnss_event_handler_set(gnss_event_handler) != 0) {
    		LOG_ERR("Failed to set GNSS event handler");
    		return;
    	}
    
    	if (nrf_modem_gnss_fix_interval_set(CONFIG_GNSS_PERIODIC_INTERVAL) != 0) {
    		LOG_ERR("Failed to set GNSS fix interval");
    		return;
    	}
    
    	if (nrf_modem_gnss_fix_retry_set(CONFIG_GNSS_PERIODIC_TIMEOUT) != 0) {
    		LOG_ERR("Failed to set GNSS fix retry");
    		return;
    	}
    	/* STEP 11 - Start the GNSS receiver*/
    	LOG_INF("Starting GNSS");
    	if (nrf_modem_gnss_start() != 0) {
    		LOG_ERR("Failed to start GNSS");
    		return;
    	}	
    	sms_handle = sms_register_listener(sms_callback,NULL);
    	if (sms_handle<0){
    		LOG_INF("SMS handle invalid");
    		return;
    	}
    	/* STEP 12.2 - Log the current system uptime */
    	gnss_start_time = k_uptime_get();
    	// while(1){
    	// 	if (k_sem_take(&text_ready,K_FOREVER)==0){
    	// 		LOG_INF("Deactivate GNSS");
    	// 		if (lte_lc_func_mode_set(LTE_LC_FUNC_MODE_DEACTIVATE_GNSS) != 0) {
    	// 			LOG_ERR("Failed to activate GNSS functional mode");
    	// 			return;
    	// 		}
    	// 		k_msleep(100);
    	// 		if (sms_send_text("+","Fix found")!=0)
    	// 			LOG_INF("Failed to SMS fix");
    	// 		k_msleep(100);
    			
    	// 		if (lte_lc_func_mode_set(LTE_LC_FUNC_MODE_ACTIVATE_GNSS) != 0) {
    	// 			LOG_ERR("Failed to activate GNSS functional mode");
    	// 			return;
    	// 		}
    	// 	}
    	// }
    }
    
    

    #
    # Copyright (c) 2019 Nordic Semiconductor ASA
    #
    # SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
    #
    
    # Logging
    CONFIG_LOG=y
    
    # Button and LED support
    CONFIG_DK_LIBRARY=y
    
    # Newlib
    CONFIG_NEWLIB_LIBC=y
    # STEP 2.2 - Enable printing of floating-points
    CONFIG_NEWLIB_LIBC_FLOAT_PRINTF=y
    CONFIG_FPU=y
    
    # Network
    CONFIG_NETWORKING=y
    CONFIG_NET_NATIVE=n
    CONFIG_NET_SOCKETS=y
    CONFIG_NET_SOCKETS_OFFLOAD=y
    CONFIG_NET_SOCKETS_POSIX_NAMES=y
    
    # Memory
    CONFIG_HEAP_MEM_POOL_SIZE=4096
    CONFIG_MAIN_STACK_SIZE=4096
    
    # Modem library
    CONFIG_NRF_MODEM_LIB=y
    
    # LTE link control
    CONFIG_LTE_LINK_CONTROL=y
    CONFIG_LTE_AUTO_INIT_AND_CONNECT=n
    
    CONFIG_LTE_NETWORK_MODE_LTE_M_NBIOT_GPS=y
    
    CONFIG_MODEM_ANTENNA_GNSS_EXTERNAL=y
    CONFIG_MODEM_ANTENNA_GNSS_ONBOARD=n
    CONFIG_SMS=y
    
    CONFIG_LTE_PSM_REQ_RPTAU="10100101"
    CONFIG_LTE_PSM_REQ_RAT="00001000"
    
    # CONFIG_LTE_EDRX_REQ=y
    # CONFIG_LTE_EDRX_REQ_VALUE_LTE_M="1010"
    
    CONFIG_RESET_ON_FATAL_ERROR=n
    

  • silwyr said:
    Whatis the second CONFIG option that should be changed?

    My appologies. That should be CONFIG_THREAD_NAME=y.

    But if the application no longer crashes after you started using a workqueue, this point is moot.

    silwyr said:
    For receiving SMSes I'm not so sure what to do, as currently they are received sometimes at near start up of the program and status report for sent message is received. 

    I am not sure if I understand what you mean here.

    Receiving SMSen is handled by the sms library, which uses the system workqueue to call the callback you register.

Related