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.