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.

Related