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.