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

MQTT blocks restarting GPS?

Hi,

I'm writing a program that swaps between LTE and GPS to send the device's location to AWS over MQTT. I am able to connect to LTE and AWS, then swap to GPS and get a fix, and swap back to LTE. However, when I then try to go back to GPS, I get a bsd recoverable error 3, and it appears I cannot communicate over the GPS socket.

If I have everything EXCEPT connecting to MQTT, I am able to freely swap between LTE and GPS.

I've attached my code below:

called by main():

void test_gps(){

    spoof(false);

    led_setup();
    button_setup();

// Storage
    // Set up certificates before nvs or else permission errors
    provision_certificates();

    nvs_setup();
    printk("\nNVS set up\n");
//---

    k_sleep(1000);

//// MQTT
    int err;
    struct mqtt_client client;
    struct sockaddr_storage broker;
    struct pollfd fds;

    s64_t timer = k_uptime_get();

    begin_lte_only();
    lte_lc_offline();
    modem_configure();
    lte_lc_edrx_req(true);

    client_init(&client, &broker, CONFIG_MQTT_BROKER_HOSTNAME);
    aws_fota_init(&client, CONFIG_APP_VERSION, aws_fota_cb_handler);
    err = mqtt_connect(&client);
    if (err != 0) {
            printk("ERROR: mqtt_connect %d\n", err);
    }
    printk("MQTT Connected");
    fds_init(&client, &fds);
    boot_write_img_confirmed();
////---

// Defs
    GPS_Logging_Off();
    bool do_gps = false;

    bool do_lte = true;
    s64_t publish_timer = k_uptime_get();
    s64_t live_timer = k_uptime_get();

    s64_t loop_timer = k_uptime_get();
//---

    printk("\nLoop starting\n");
    while(1){

// GPS Loop
        if(detect_press(2)){
            if(do_gps){
                printk("\ngps off\n");
                GPS_Disable();

                do_gps = false;
            }else{
                mqtt_disconnect(&client);
                lte_lc_offline();
                printk("\ngps on");
                gps_off_lte_off();

                GPS_Init();
                GPS_Logging_Off();
                printk("\nGPS Initialized\n");
                GPS_Enable();
                printk("\nGPS Enabled\n");
                do_gps = true;
                do_lte = false;
            }
        }


        if(detect_press(1)){
            begin_lte_only();
            lte_lc_offline();
            modem_configure();
            lte_lc_edrx_req(true);

            publish_timer = k_uptime_get();
            live_timer = k_uptime_get();
            
            
            struct mqtt_client client;
            struct sockaddr_storage broker;
            struct pollfd fds;
            client_init(&client, &broker, CONFIG_MQTT_BROKER_HOSTNAME);
            aws_fota_init(&client, CONFIG_APP_VERSION, aws_fota_cb_handler);
            err = mqtt_connect(&client);
            if (err != 0) {
                    printk("ERROR: mqtt_connect %d\n", err);
            }
            printk("MQTT Connected");
            fds_init(&client, &fds);
            boot_write_img_confirmed();

            do_lte = true;  
        }

        if(do_gps) GPS_State_Machine(&fs);
//---   
//---
        while(k_uptime_get()-loop_timer <= 20);
        loop_timer = k_uptime_get();
    }
}

GPS code:

void GPS_State_Machine(struct nvs_fs* fs){
    switch(gps_state){
		case GPS_IDLE:
                    
                    // Record a coordinate every gps_update_rate period
                    if(k_uptime_get()-t_last_location_recorded >= GPS_Update_Rate(-1)){
                        t_last_location_recorded = k_uptime_get();
                        gps_state = RECORD_COORDINATE;
                    }
                    break;

		case RECORD_COORDINATE:{

                    // Record a location in memory
                    toggle_led(1);
                    update_gps_data(&gps_data);

                    if(log_data){
                        save_gps_data(&last_fix, fs);
                    }

                    toggle_led(1);
                    gps_state = GPS_IDLE;
                    break;}

                case GET_FIX:
                    // Ping every FIX_PING_RATE period to try to get a fix
                    if(k_uptime_get()-t_last_ping >= FIX_PING_RATE){
                        t_last_ping = k_uptime_get();
                        toggle_led(2);

                        if(!got_first_fix){
                            get_gps_fix(&gps_data);
                        }
                        if(got_first_fix){
                            led_on(2);
                            gps_state = GPS_IDLE;
                        }

                    }
                    break;
	}
}


int get_gps_fix(nrf_gnss_data_frame_t* gps_data){
    /*
        Records data from gps and prints it out every 500ms until a fix is detected.
    */

    if(spoof_gps_data){
        printk("Spoofed data, switching out of getting fix");
        gps_state = GPS_IDLE;
        return 0;
    }

    do {
    
    } while(process_gps_data(gps_data) > 0); // Read data from GPS
     
    if(!got_first_fix){
        cnt = (cnt+1)%4;
        printk("\033[1;1H");
        printk("\033[2J");
        print_satellite_stats(gps_data);
        printk("\nScanning: [%c] ", update_indicator[cnt]);
    }
    else if(k_uptime_get()-fix_timestamp >= 1){
        display_gps_fixed(gps_data);
    }

    return 0;
}

int process_gps_data(nrf_gnss_data_frame_t *gps_data)
{
	int retval;

	retval = nrf_recv(gps_socket, gps_data, sizeof(nrf_gnss_data_frame_t), NRF_MSG_DONTWAIT);

	if (retval > 0) {

		switch (gps_data->data_id) {
		case NRF_GNSS_PVT_DATA_ID:
                        
                        printk("\nPVT data received\n");
			if ((gps_data->pvt.flags &
				NRF_GNSS_PVT_FLAG_FIX_VALID_BIT)
				== NRF_GNSS_PVT_FLAG_FIX_VALID_BIT) {

				if (!got_first_fix) {
					got_first_fix = true;
				}

				fix_timestamp = k_uptime_get();
				memcpy(&last_fix, gps_data, sizeof(nrf_gnss_data_frame_t));

				nmea_string_cnt = 0;
			}
			break;

		case NRF_GNSS_NMEA_DATA_ID:
                        printk("\nNMEA data received\n");
			if (nmea_string_cnt < 10) {
				memcpy(nmea_strings[nmea_string_cnt++],
				       gps_data->nmea,
				       retval);
			}
			break;

		default:
                        printk("\nBytes read\n");
			break;
		}
	}else{
                printk("\nProcess GPS Data error: %d", retval);
        }

	return retval;
}


void GPS_Init(){
    /*
        Sets default variable values and sets the socket options for the GPS.
    */
    
    UART_Output_On();
    GPS_Logging_On();
    GPS_Update_Rate(1000); 
    loc_id = 1;
    if(spoof_gps_data){
        gps_data = office;
        gps_state = GPS_IDLE;
        UART_Output_Off();
    }else{
        gps_state = GET_FIX;
    }
    got_first_fix = false;
    t_last_location_recorded = k_uptime_get();
    
}

int GPS_Enable(){
    if(!spoof_gps_data){
        int rv = init_app();
        if(rv) printk("init_app failure: rv = %d", rv);
    }

    return 0;
}


int enable_gps(void)
{
 	int  at_sock;
 	int  bytes_sent;
 	int  bytes_received;
 	char buf[2];

 	at_sock = socket(AF_LTE, 0, NPROTO_AT);
 	if (at_sock < 0) {
                printk("\nBad at_sock\n");
 		return -1;
 	}

 	for (int i = 0; i < ARRAY_SIZE(at_commands); i++) {
 		bytes_sent = send(at_sock, at_commands[i],
 				  strlen(at_commands[i]), 0);

 		if (bytes_sent < 0) {
                        printk("Negative Bytes");
 			close(at_sock);
 			return -1;
 		}

 		do {
 			bytes_received = recv(at_sock, buf, 2, 0);
 		} while (bytes_received == 0);

 		if (memcmp(buf, "OK", 2) != 0) {
                        printk("\nNot OK: %s, %d\n", buf, i);
 			close(at_sock);
 			return -1;
 		}
 	}

 	close(at_sock);

 	return 0;
 }

int init_app(void)
{
        /*
            Initializes GPS settings and socket for GPS comms.
        */
	u16_t fix_retry     = 0;
	u16_t fix_interval  = 1;
	u16_t nmea_mask     = NRF_CONFIG_NMEA_GSV_MASK |
			      NRF_CONFIG_NMEA_GSA_MASK |
			      NRF_CONFIG_NMEA_GLL_MASK |
			      NRF_CONFIG_NMEA_GGA_MASK |
			      NRF_CONFIG_NMEA_RMC_MASK;
	int   retval;

	if (enable_gps() != 0) {
		printk("Failed to enable GPS\n");
		return -1;
	}

	gps_socket = nrf_socket(NRF_AF_LOCAL, NRF_SOCK_DGRAM, NRF_PROTO_GNSS);

	if (gps_socket >= 0) {
		printk("Socket created\n");
	} else {
		printk("Could not init socket (err: %d)\n", gps_socket);
		return -1;
	}

	retval = nrf_setsockopt(gps_socket,
				NRF_SOL_GNSS,
				NRF_SO_GNSS_FIX_RETRY,
				&fix_retry,
				sizeof(uint16_t));

	if (retval != 0) {
		printk("Failed to set fix retry value: %d\n", retval);
		return -1;
	}

	retval = nrf_setsockopt(gps_socket,
				NRF_SOL_GNSS,
				NRF_SO_GNSS_FIX_INTERVAL,
				&fix_interval,
				sizeof(uint16_t));

	if (retval != 0) {
		printk("Failed to set fix interval value\n");
		return -1;
	}


//------ ADDED USE CASE PARAM FOR GPS REENABLE

	retval = nrf_setsockopt(gps_socket,
				NRF_SOL_GNSS,
				NRF_SO_GNSS_USE_CASE,
				&use_case,
				sizeof(uint8_t));

	if (retval != 0) {
		printk("Failed to set use case value: %d\n", retval);
                while(1);
		return -1;
	}
//-----



	retval = nrf_setsockopt(gps_socket,
				NRF_SOL_GNSS,
				NRF_SO_GNSS_NMEA_MASK,
				&nmea_mask,
				sizeof(uint16_t));

	if (retval != 0) {
		printk("Failed to set nmea mask\n");
		return -1;
	}

	retval = nrf_setsockopt(gps_socket,
				NRF_SOL_GNSS,
				NRF_SO_GNSS_START,
				NULL,
				0);

	if (retval != 0) {
		printk("Failed to start GPS\n");
		return -1;
	}

	return 0;
}


AT command swapping code:

int gps_on_lte_off(){
    const char* cmds[] = {"AT+CFUN=4", "AT\%XSYSTEMMODE=0,0,1,0", "AT+CFUN=1"};
    
    int at_socket = socket(AF_LTE, 0, NPROTO_AT);
    if(at_socket < 0){
        printk("Socket error");
        return at_socket;
    }

    char buf[2];
    int bytes_received;
    s64_t timer;
    for(int ix=0; ix < 3; ix++){
        if(send(at_socket, cmds[ix], strlen(cmds[ix]), 0) < 0){
            printk("send error: %s", cmds[ix]);
            return -1;
        }
        
        do {
                bytes_received = recv(at_socket, buf, 2, 0);
        } while (bytes_received == 0);

        if (memcmp(buf, "OK", 2) != 0) {
                printk("\nNot OK: %s, %s\n", buf, cmds[ix]);
                close(at_socket);
                return -1;
        }

        timer = k_uptime_get();
        while(k_uptime_get()-timer < 500);
    }

    close(at_socket);
    return 0;
}



int gps_off_lte_on(){
    const char* cmds[] = {"AT+CFUN=4", "AT\%XSYSTEMMODE=1,0,0,0", "AT+CFUN=1"};
    
    int at_socket = socket(AF_LTE, 0, NPROTO_AT);
    if(at_socket < 0){
        printk("Socket error");
        return at_socket;
    }

    char buf[2];
    int bytes_received;
    s64_t timer;
    for(int ix=0; ix < 3; ix++){
        if(send(at_socket, cmds[ix], strlen(cmds[ix]), 0) < 0){
            printk("send error: %s", cmds[ix]);
            return -1;
        }
        
        do {
                bytes_received = recv(at_socket, buf, 2, 0);
        } while (bytes_received == 0);

        if (memcmp(buf, "OK", 2) != 0) {
                printk("\nNot OK: %s, %s\n", buf, cmds[ix]);
                close(at_socket);
                return -1;
        }

        timer = k_uptime_get();
        while(k_uptime_get()-timer < 500);
    }

    close(at_socket);
    return 0;
}


int gps_on_lte_on(){
    const char* cmds[] = {"AT+CFUN=4", "AT\%XSYSTEMMODE=1,0,1,0", "AT+CFUN=1"};
    
    int at_socket = socket(AF_LTE, 0, NPROTO_AT);
    if(at_socket < 0){
        printk("Socket error");
        return at_socket;
    }

    char buf[2];
    int bytes_received;
    s64_t timer;
    for(int ix=0; ix < 3; ix++){
        if(send(at_socket, cmds[ix], strlen(cmds[ix]), 0) < 0){
            printk("send error: %s", cmds[ix]);
            return -1;
        }
        
        do {
                bytes_received = recv(at_socket, buf, 2, 0);
        } while (bytes_received == 0);

        if (memcmp(buf, "OK", 2) != 0) {
                printk("\nNot OK: %s, %s\n", buf, cmds[ix]);
                close(at_socket);
                return -1;
        }

        timer = k_uptime_get();
        while(k_uptime_get()-timer < 500);
    }

    close(at_socket);
    return 0;
}


int gps_off_lte_off(){
    const char* cmds[] = {"AT+CFUN=4", "AT\%XSYSTEMMODE=0,0,0,0", "AT+CFUN=1"};
    
    int at_socket = socket(AF_LTE, 0, NPROTO_AT);
    if(at_socket < 0){
        printk("Socket error");
        return at_socket;
    }

    char buf[2];
    int bytes_received;
    s64_t timer;
    for(int ix=0; ix < 3; ix++){
        if(send(at_socket, cmds[ix], strlen(cmds[ix]), 0) < 0){
            printk("send error: %s", cmds[ix]);
            return -1;
        }
        
        do {
                bytes_received = recv(at_socket, buf, 2, 0);
        } while (bytes_received == 0);

        if (memcmp(buf, "OK", 2) != 0) {
                printk("\nNot OK: %s, %s\n", buf, cmds[ix]);
                close(at_socket);
                return -1;
        }

        timer = k_uptime_get();
        while(k_uptime_get()-timer < 500);
    }

    close(at_socket);
    return 0;
}


int begin_lte_only(){
    const char* cmds[] = {"AT+CFUN=4", "AT\%XSYSTEMMODE=1,0,0,0", "AT+CFUN=1"};
//    const char* cmds[] = {"AT\%XSYSTEMMODE=1,0,0,0", "AT+CFUN=1"};

    int at_socket = socket(AF_LTE, 0, NPROTO_AT);
    if(at_socket < 0){
        printk("Socket error");
        return at_socket;
    }

    char buf[2];
    int bytes_received;
    s64_t timer;
    for(int ix=0; ix < 3; ix++){
        if(send(at_socket, cmds[ix], strlen(cmds[ix]), 0) < 0){
            printk("send error: %s", cmds[ix]);
            return -1;
        }
        
        do {
                bytes_received = recv(at_socket, buf, 2, 0);
        } while (bytes_received == 0);

        if (memcmp(buf, "OK", 2) != 0) {
                printk("\nNot OK: %s, %s\n", buf, cmds[ix]);
                close(at_socket);
                return -1;
        }

        timer = k_uptime_get();
        while(k_uptime_get()-timer < 500);
    }

    close(at_socket);
    return 0;
}

int swap_to_gps_only(){
    const char* cmds[] = {"AT+CFUN=4", "AT\%XSYSTEMMODE=0,0,1,0", "AT\%XMAGPIO=1,0,0,1,1,1574,1577", "AT+CFUN=1"};
    
    int at_socket = socket(AF_LTE, 0, NPROTO_AT);
    if(at_socket < 0){
        printk("Socket error");
        return at_socket;
    }

    char buf[2];
    int bytes_received;
    s64_t timer;
    for(int ix=0; ix < 4; ix++){
        if(send(at_socket, cmds[ix], strlen(cmds[ix]), 0) < 0){
            printk("send error: %s", cmds[ix]);
            return -1;
        }
        
        do {
                bytes_received = recv(at_socket, buf, 2, 0);
        } while (bytes_received == 0);

        if (memcmp(buf, "OK", 2) != 0) {
                printk("\nNot OK: %s, %s\n", buf, cmds[ix]);
                close(at_socket);
                return -1;
        }

        timer = k_uptime_get();
        while(k_uptime_get()-timer < 500);
    }

    close(at_socket);
    return 0;
}


int swap_to_lte_only(){
    const char* cmds[] = {"AT+CFUN=4", "AT\%XSYSTEMMODE=1,0,0,0", "AT\%XMAGPIO", "AT+CFUN=1"};
    
    int at_socket = socket(AF_LTE, 0, NPROTO_AT);
    if(at_socket < 0){
        printk("Socket error");
        return at_socket;
    }

    char buf[2];
    int bytes_received;
    s64_t timer;
    for(int ix=0; ix < 4; ix++){
        if(send(at_socket, cmds[ix], strlen(cmds[ix]), 0) < 0){
            printk("send error: %s", cmds[ix]);
            return -1;
        }
        
        do {
                bytes_received = recv(at_socket, buf, 2, 0);
        } while (bytes_received == 0);

        if (memcmp(buf, "OK", 2) != 0) {
                printk("\nNot OK: %s, %s\n", buf, cmds[ix]);
                close(at_socket);
                return -1;
        }

        timer = k_uptime_get();
        while(k_uptime_get()-timer < 500);
    }

    close(at_socket);
    return 0;
}

int lte_systemmode(){
    
    int at_socket = socket(AF_LTE, 0, NPROTO_AT);
    if(at_socket < 0){
        printk("Socket error");
        return at_socket;
    }

    char buf[2];
    int bytes_received;
    if(send(at_socket, "AT\%XSYSTEMMODE=1,0,0,0", strlen("AT\%XSYSTEMMODE=1,0,0,0"), 0) < 0){
        printk("send error: %s", "AT\%XSYSTEMMODE=1,0,0,0");
        return -1;
    }
    
    do {
            bytes_received = recv(at_socket, buf, 2, 0);
    } while (bytes_received == 0);

    if (memcmp(buf, "OK", 2) != 0) {
            printk("\nNot OK: %s, %s\n", buf, "AT\%XSYSTEMMODE=1,0,0,0");
            close(at_socket);
            return -1;
    }

    close(at_socket);
    return 0;
}



int gps_systemmode(){
    
    int at_socket = socket(AF_LTE, 0, NPROTO_AT);
    if(at_socket < 0){
        printk("Socket error");
        return at_socket;
    }

    char buf[2];
    int bytes_received;
    if(send(at_socket, "AT\%XSYSTEMMODE=0,0,1,0", strlen("AT\%XSYSTEMMODE=0,0,1,0"), 0) < 0){
        printk("send error: %s", "AT\%XSYSTEMMODE=0,0,1,0");
        return -1;
    }
    
    do {
            bytes_received = recv(at_socket, buf, 2, 0);
    } while (bytes_received == 0);

    if (memcmp(buf, "OK", 2) != 0) {
            printk("\nNot OK: %s, %s\n", buf, "AT\%XSYSTEMMODE=0,0,1,0");
            close(at_socket);
            return -1;
    }

    close(at_socket);
    return 0;
}

Output:

***** Booting Zephyr OS build v1.14.99-ncs3-snapshot2 *****
nrf_inbuilt_key_delete(16842753, 0) => result=0
nrf_inbuilt_key_delete(16842753, 1) => result=0
nrf_inbuilt_key_delete(16842753, 2) => result=0
nrf_inbuilt_key_write => result=0
nrf_inbuilt_key_write => result=0
nrf_inbuilt_key_write => result=0

NVS set up
[00:00:04.551,025] <inf> fs_nvs: 3 Sectors of 4096 bytes
[00:00:04.551,025] <inf> fs_nvs: alloc wra: 1, 7e8
[00:00:04.551,025] <inf> fs_nvs: data wra: 1, 604
LTE Link Connecting ...
LTE Link Connected! 0
IPv4 Address 0xaa271203
client_id: nrf-352656100266173
MQTT Connected
Loop starting

gps on
GPS Initialized
Socket created

GPS Enabled

Process GPS Data error: -1
Tracking: 0 Using: 0 Unhealthy: 0
Seconds since last fix 135

Scanning: [|]
PVT data received

NMEA data received

NMEA data received

NMEA data received

NMEA data received

NMEA data received

Process GPS Data error: -1
Tracking: 0 Using: 0 Unhealthy: 0
Seconds since last fix 135

Scanning: [/]
Process GPS Data error: -1
Tracking: 0 Using: 0 Unhealthy: 0
Seconds since last fix 136

Scanning: [-]
PVT data received

NMEA data received

NMEA data received

NMEA data received

NMEA data received

NMEA data received

Process GPS Data error: -1
Tracking: 0 Using: 0 Unhealthy: 0
Seconds since last fix 136

Scanning: [\]
PVT data received

NMEA data received

NMEA data received

NMEA data received

NMEA data received

NMEA data received

Process GPS Data error: -1
Tracking: 0 Using: 0 Unhealthy: 0
Seconds since last fix 137

Scanning: [|]
Process GPS Data error: -1
Tracking: 0 Using: 0 Unhealthy: 0
Seconds since last fix 137

Scanning: [/]
gps off
LTE Link Connecting ...
LTE Link Connected! 0
IPv4 Address 0x7dc40e03
client_id: nrf-352656100266173
MQTT Connected
gps on
GPS Initialized
Socket created

GPS Enabled

Process GPS Data error: -1
Tracking: 0 Using: 0 Unhealthy: 0
Seconds since last fix 177

Scanning: [|] Err: 3

Process GPS Data error: -1
Tracking: 0 Using: 0 Unhealthy: 0
Seconds since last fix 181

Scanning: [/]
Process GPS Data error: -1
Tracking: 0 Using: 0 Unhealthy: 0
Seconds since last fix 181

Using the debugger, I was able to find that the error occurred after the call to  retval = nrf_setsockopt(gps_socket, NRF_SOL_GNSS, NRF_SO_GNSS_START, NULL, 0);

What's going wrong?

Thanks.

Parents
  • Hello!

    I don't know why MQTT is causing this problem, but I suspect it could be related to issues with the sockets.

    Which modem firmware(MFW) and NCS version are you running? I know there have been some issues with the older MFWs when it comes to opening and closing sockets often. Furthermore: using the newest MFW I don't think it's necessary to change the systemmode each time you switch, it should be possible to have GPS and LTE enabled at the same time.

    All the best, 
    Carl Richard

Reply
  • Hello!

    I don't know why MQTT is causing this problem, but I suspect it could be related to issues with the sockets.

    Which modem firmware(MFW) and NCS version are you running? I know there have been some issues with the older MFWs when it comes to opening and closing sockets often. Furthermore: using the newest MFW I don't think it's necessary to change the systemmode each time you switch, it should be possible to have GPS and LTE enabled at the same time.

    All the best, 
    Carl Richard

Children
Related