I'm attempting t to turn on and off GPS function while LTE is on, but it doesn't work out. I merged mqtt_simple and gps example programs into a new project. What's wrong with the program?
In configure_gps_off_on function, buf stores "ERROR" in the line of bytes_received = recv(at_sock, buf, 2, 0), which means that receiving data through socket does not work.
ncs version: 1.0.0
In version 1.0.0, is it possible to use LTE and GPS at the same time?
<prj.conf> # General config CONFIG_TEST_RANDOM_GENERATOR=y CONFIG_NEWLIB_LIBC=y CONFIG_NEWLIB_LIBC_FLOAT_PRINTF=y # Networking CONFIG_NETWORKING=y CONFIG_NET_SOCKETS_OFFLOAD=y CONFIG_NET_SOCKETS=y CONFIG_NET_SOCKETS_POSIX_NAMES=y CONFIG_STDOUT_CONSOLE=y CONFIG_LOG=y CONFIG_LOG_DEFAULT_LEVEL=4 # LTE link control CONFIG_LTE_LINK_CONTROL=y CONFIG_LTE_AUTO_INIT_AND_CONNECT=n # BSD library CONFIG_BSD_LIBRARY=y # AT Host CONFIG_UART_INTERRUPT_DRIVEN=y CONFIG_AT_HOST_LIBRARY=y # MQTT CONFIG_MQTT_LIB=y CONFIG_MQTT_LIB_TLS=n # Appliaction CONFIG_MQTT_PUB_TOPIC="myPubTopic" CONFIG_MQTT_SUB_TOPIC="mySubTopic" CONFIG_MQTT_CLIENT_ID="myClientID" CONFIG_MQTT_BROKER_HOSTNAME="xxxxxxxx.com" CONFIG_MQTT_BROKER_PORT=xxxx # Main thread CONFIG_MAIN_THREAD_PRIORITY=7 CONFIG_MAIN_STACK_SIZE=4096 CONFIG_HEAP_MEM_POOL_SIZE=1024 # Disable native network stack to save some memory CONFIG_NET_IPV4=n CONFIG_NET_IPV6=n CONFIG_NET_UDP=n CONFIG_NET_TCP=n CONFIG_NET_RX_STACK_SIZE=256 CONFIG_NET_TX_STACK_SIZE=256
<main.c> /* * Copyright (c) 2018 Nordic Semiconductor ASA * * SPDX-License-Identifier: LicenseRef-BSD-5-Clause-Nordic */ #include <zephyr.h> #include <stdio.h> #include <uart.h> #include <string.h> #include <net/mqtt.h> #include <nrf_socket.h> #include <net/socket.h> #include <lte_lc.h> #include <stdio.h> #define MQTT_USERNAME "username" #define MQTT_PASSWORD "password" #define AT_XSYSTEMMODE_EN_M1_GPS "AT\%XSYSTEMMODE=1,0,1,0" // %XSYSTEMMODE=<M1_support>,<NB1_support>,<GNSS_support>,<LTE_preference> #define AT_XSYSTEMMODE_EN_M1 "AT\%XSYSTEMMODE=1,0,0,0" #define AT_CFUN_EN_MODEM "AT+CFUN=1" /* Set the modem functional mode. * 0 – Power off * 1 – Normal mode * 4 – Offline mode * 44 – Offline mode without shutting down UICC */ #ifdef CONFIG_BOARD_NRF9160_PCA10090NS #define AT_MAGPIO_EN_GPS "AT\%XMAGPIO=1,0,0,1,1,1574,1577" // %XMAGPIO=<MAGPIO0>,<MAGPIO1>,<MAGPIO2>,<The number of frequency ranges>,<state_0>,<flo_0>,<fhi_0><state_1>,<flo_1>,<fhi_1>,... #define AT_MAGPIO_DIS "AT\%XMAGPIO" #endif #define GPS_EN true #define GPS_DIS false static int fd; static char nmea_strings[10][NRF_GNSS_NMEA_MAX_LEN]; static u32_t nmea_string_cnt; static bool got_first_fix; static bool update_terminal; static u64_t fix_timestamp; nrf_gnss_data_frame_t last_fix; /* Buffers for MQTT client. */ static u8_t rx_buffer[CONFIG_MQTT_MESSAGE_BUFFER_SIZE]; static u8_t tx_buffer[CONFIG_MQTT_MESSAGE_BUFFER_SIZE]; static u8_t payload_buf[CONFIG_MQTT_PAYLOAD_BUFFER_SIZE]; /* The mqtt client struct */ static struct mqtt_client client; /* MQTT Broker details. */ static struct sockaddr_storage broker; /* Connected flag */ static bool connected; /* File descriptor */ static struct pollfd fds; #if defined(CONFIG_BSD_LIBRARY) /**@brief Recoverable BSD library error. */ void bsd_recoverable_error_handler(uint32_t err) { printk("bsdlib recoverable error: %u\n", err); } /**@brief Irrecoverable BSD library error. */ void bsd_irrecoverable_error_handler(uint32_t err) { printk("bsdlib irrecoverable error: %u\n", err); __ASSERT_NO_MSG(false); } #endif /* defined(CONFIG_BSD_LIBRARY) */ /* GPS setting*/ static int configure_gps_off_on(bool status) { int at_sock; int bytes_sent; int bytes_received; char buf[2]; char *at_commands[3]; if(status == GPS_EN){ at_commands[0] = AT_XSYSTEMMODE_EN_M1_GPS; at_commands[1] = AT_MAGPIO_EN_GPS; } else { at_commands[0] = AT_XSYSTEMMODE_EN_M1; at_commands[1] = AT_MAGPIO_DIS; } at_commands[2] = AT_CFUN_EN_MODEM; printf("at_commands[0] = %s\n", at_commands[0]); printf("at_commands[1] = %s\n", at_commands[1]); printf("at_commands[2] = %s\n", at_commands[2]); at_sock = socket(AF_LTE, 0, NPROTO_AT); // retunr 4 printk("at_sock = %u\n", at_sock); if (at_sock < 0) { printk("Error1\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); printk("at_commands[i] = %s\n", at_commands[i]); printk("strlen(at_commands[i]) = %u\n", strlen(at_commands[i])); if (bytes_sent < 0) { close(at_sock); printk("Error2\n"); return -1; } do { bytes_received = recv(at_sock, buf, 2, 0); // this is not successful } while (bytes_received == 0); printk("buf = %s\n", buf); // "ER" if (memcmp(buf, "OK", 2) != 0) { close(at_sock); printk("Error3\n"); // reach here return -1; } } close(at_sock); return 0; } static int init_gps(void) { 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 (configure_gps_off_on(GPS_EN) != 0) { printk("Failed to enable GPS\n"); return -1; } fd = nrf_socket(NRF_AF_LOCAL, NRF_SOCK_DGRAM, NRF_PROTO_GNSS); if (fd >= 0) { printk("Socket created\n"); } else { printk("Could not init socket (err: %d)\n", fd); return -1; } retval = nrf_setsockopt(fd, NRF_SOL_GNSS, NRF_SO_GNSS_FIX_RETRY, &fix_retry, sizeof(uint16_t)); if (retval != 0) { printk("Failed to set fix retry value\n"); return -1; } retval = nrf_setsockopt(fd, 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; } retval = nrf_setsockopt(fd, 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(fd, NRF_SOL_GNSS, NRF_SO_GNSS_START, NULL, 0); if (retval != 0) { printk("Failed to start GPS\n"); return -1; } return 0; } int process_gps_data(nrf_gnss_data_frame_t *gps_data) { int retval; retval = nrf_recv(fd, 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: 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; update_terminal = true; } break; case NRF_GNSS_NMEA_DATA_ID: if (nmea_string_cnt < 10) { memcpy(nmea_strings[nmea_string_cnt++], gps_data->nmea, retval); } break; default: break; } } return retval; } static void print_pvt_data(nrf_gnss_data_frame_t *pvt_data) { printf("Longitude: %f\n", pvt_data->pvt.longitude); printf("Latitude: %f\n", pvt_data->pvt.latitude); printf("Altitude: %f\n", pvt_data->pvt.altitude); printf("Speed: %f\n", pvt_data->pvt.speed); printf("Heading: %f\n", pvt_data->pvt.heading); printk("Date: %02u-%02u-%02u\n", pvt_data->pvt.datetime.day, pvt_data->pvt.datetime.month, pvt_data->pvt.datetime.year); printk("Time (UTC): %02u:%02u:%02u\n", pvt_data->pvt.datetime.hour, pvt_data->pvt.datetime.minute, pvt_data->pvt.datetime.seconds); } /**@brief Function to print strings without null-termination */ static void data_print(u8_t *prefix, u8_t *data, size_t len) { char buf[len + 1]; memcpy(buf, data, len); buf[len] = 0; printk("%s%s\n", prefix, buf); } /**@brief Function to publish data on the configured topic */ static int data_publish(struct mqtt_client *c, enum mqtt_qos qos, u8_t *data, size_t len) { struct mqtt_publish_param param; param.message.topic.qos = qos; param.message.topic.topic.utf8 = CONFIG_MQTT_PUB_TOPIC; param.message.topic.topic.size = strlen(CONFIG_MQTT_PUB_TOPIC); param.message.payload.data = data; param.message.payload.len = len; param.message_id = sys_rand32_get(); param.dup_flag = 0; param.retain_flag = 0; data_print("Publishing: ", data, len); printk("to topic: %s len: %u\n", CONFIG_MQTT_PUB_TOPIC, (unsigned int)strlen(CONFIG_MQTT_PUB_TOPIC)); return mqtt_publish(c, ¶m); } /**@brief Function to subscribe to the configured topic */ static int subscribe(void) { struct mqtt_topic subscribe_topic = { .topic = { .utf8 = CONFIG_MQTT_SUB_TOPIC, .size = strlen(CONFIG_MQTT_SUB_TOPIC) }, .qos = MQTT_QOS_1_AT_LEAST_ONCE }; const struct mqtt_subscription_list subscription_list = { .list = &subscribe_topic, .list_count = 1, .message_id = 1234 }; printk("Subscribing to: %s len %u\n", CONFIG_MQTT_SUB_TOPIC, (unsigned int)strlen(CONFIG_MQTT_SUB_TOPIC)); return mqtt_subscribe(&client, &subscription_list); } /**@brief Function to read the published payload. */ static int publish_get_payload(struct mqtt_client *c, size_t length) { u8_t *buf = payload_buf; u8_t *end = buf + length; if (length > sizeof(payload_buf)) { return -EMSGSIZE; } while (buf < end) { int ret = mqtt_read_publish_payload(c, buf, end - buf); if (ret < 0) { int err; if (ret != -EAGAIN) { return ret; } printk("mqtt_read_publish_payload: EAGAIN\n"); err = poll(&fds, 1, K_SECONDS(CONFIG_MQTT_KEEPALIVE)); if (err > 0 && (fds.revents & POLLIN) == POLLIN) { continue; } else { return -EIO; } } if (ret == 0) { return -EIO; } buf += ret; } return 0; } /**@brief MQTT client event handler */ void mqtt_evt_handler(struct mqtt_client *const c, const struct mqtt_evt *evt) { int err; switch (evt->type) { case MQTT_EVT_CONNACK: if (evt->result != 0) { printk("MQTT connect failed %d\n", evt->result); break; } connected = true; printk("[%s:%d] MQTT client connected!\n", __func__, __LINE__); subscribe(); break; case MQTT_EVT_DISCONNECT: printk("[%s:%d] MQTT client disconnected %d\n", __func__, __LINE__, evt->result); connected = false; break; case MQTT_EVT_PUBLISH: { const struct mqtt_publish_param *p = &evt->param.publish; printk("[%s:%d] MQTT PUBLISH result=%d len=%d\n", __func__, __LINE__, evt->result, p->message.payload.len); err = publish_get_payload(c, p->message.payload.len); if (err >= 0) { data_print("Received: ", payload_buf, p->message.payload.len); /* Echo back received data */ data_publish(&client, MQTT_QOS_1_AT_LEAST_ONCE, payload_buf, p->message.payload.len); } else { printk("mqtt_read_publish_payload: Failed! %d\n", err); printk("Disconnecting MQTT client...\n"); err = mqtt_disconnect(c); if (err) { printk("Could not disconnect: %d\n", err); } } } break; case MQTT_EVT_PUBACK: if (evt->result != 0) { printk("MQTT PUBACK error %d\n", evt->result); break; } printk("[%s:%d] PUBACK packet id: %u\n", __func__, __LINE__, evt->param.puback.message_id); break; case MQTT_EVT_SUBACK: if (evt->result != 0) { printk("MQTT SUBACK error %d\n", evt->result); break; } printk("[%s:%d] SUBACK packet id: %u\n", __func__, __LINE__, evt->param.suback.message_id); break; default: printk("[%s:%d] default: %d\n", __func__, __LINE__, evt->type); break; } } /**@brief Resolves the configured hostname and * initializes the MQTT broker structure */ static void broker_init(void) { int err; struct addrinfo *result; struct addrinfo *addr; struct addrinfo hints = { .ai_family = AF_INET, .ai_socktype = SOCK_STREAM }; err = getaddrinfo(CONFIG_MQTT_BROKER_HOSTNAME, NULL, &hints, &result); if (err) { printk("ERROR: getaddrinfo failed %d\n", err); return; } addr = result; err = -ENOENT; /* Look for address of the broker. */ while (addr != NULL) { /* IPv4 Address. */ if (addr->ai_addrlen == sizeof(struct sockaddr_in)) { struct sockaddr_in *broker4 = ((struct sockaddr_in *)&broker); char ipv4_addr[NET_IPV4_ADDR_LEN]; broker4->sin_addr.s_addr = ((struct sockaddr_in *)addr->ai_addr) ->sin_addr.s_addr; broker4->sin_family = AF_INET; broker4->sin_port = htons(CONFIG_MQTT_BROKER_PORT); inet_ntop(AF_INET, &broker4->sin_addr.s_addr, ipv4_addr, sizeof(ipv4_addr)); printk("IPv4 Address found %s\n", ipv4_addr); break; } else { printk("ai_addrlen = %u should be %u or %u\n", (unsigned int)addr->ai_addrlen, (unsigned int)sizeof(struct sockaddr_in), (unsigned int)sizeof(struct sockaddr_in6)); } addr = addr->ai_next; break; } /* Free the address. */ freeaddrinfo(result); } /**@brief Initialize the MQTT client structure */ static void client_init(struct mqtt_client *client) { mqtt_client_init(client); broker_init(); static struct mqtt_utf8 password; static struct mqtt_utf8 user_name; password.utf8 = (u8_t*)MQTT_PASSWORD; password.size = strlen(MQTT_PASSWORD); user_name.utf8 = (u8_t*)MQTT_USERNAME; user_name.size = strlen(MQTT_USERNAME); /* MQTT client configuration */ client->broker = &broker; client->evt_cb = mqtt_evt_handler; client->client_id.utf8 = (u8_t *)CONFIG_MQTT_CLIENT_ID; client->client_id.size = strlen(CONFIG_MQTT_CLIENT_ID); client->password = &password; client->user_name = &user_name; client->protocol_version = MQTT_VERSION_3_1_1; /* MQTT buffers configuration */ client->rx_buf = rx_buffer; client->rx_buf_size = sizeof(rx_buffer); client->tx_buf = tx_buffer; client->tx_buf_size = sizeof(tx_buffer); /* MQTT transport configuration */ client->transport.type = MQTT_TRANSPORT_NON_SECURE; } /**@brief Initialize the file descriptor structure used by poll. */ static int fds_init(struct mqtt_client *c) { if (c->transport.type == MQTT_TRANSPORT_NON_SECURE) { fds.fd = c->transport.tcp.sock; } else { #if defined(CONFIG_MQTT_LIB_TLS) fds.fd = c->transport.tls.sock; #else return -ENOTSUP; #endif } fds.events = POLLIN; return 0; } /**@brief Configures modem to provide LTE link. Blocks until link is * successfully established. */ static void modem_configure(void) { #if defined(CONFIG_LTE_LINK_CONTROL) if (IS_ENABLED(CONFIG_LTE_AUTO_INIT_AND_CONNECT)) { /* Do nothing, modem is already turned on * and connected. */ } else { int err; printk("LTE Link Connecting ...\n"); err = lte_lc_init_and_connect(); __ASSERT(err == 0, "LTE link could not be established."); printk("LTE Link Connected!\n"); } #endif } int8_t poll_and_check_rcv_data(u32_t interval_msec){ int err = poll(&fds, 1, interval_msec); // Check if any data comes through LTE-M. When it is waiting for an incoming data, it sleeps int8_t ret = 0; if (err < 0) { printk("ERROR: poll %d\n", errno); return -1; } /* Check if data is received through LTE-M */ /* Caution!! These are mandatory */ if ((fds.revents & POLLIN) == POLLIN) { err = mqtt_input(&client); // if a publish event comes, mqtt_evt_handler is called here if (err != 0) { printk("ERROR: mqtt_input %d\n", err); return -1; } } if ((fds.revents & POLLERR) == POLLERR) { printk("POLLERR\n"); return -1; } if ((fds.revents & POLLNVAL) == POLLNVAL) { printk("POLLNVAL\n"); return -1; } return ret; } void main(void) { int err; printk("The MQTT simple sample started\n"); modem_configure(); client_init(&client); err = mqtt_connect(&client); if (err != 0) { printk("ERROR: mqtt_connect %d\n", err); return; } err = fds_init(&client); if (err != 0) { printk("ERROR: fds_init %d\n", err); return; } poll_and_check_rcv_data(K_SECONDS(5)); /* GPS variables */ nrf_gnss_data_frame_t gps_data; while (1) { printk("Staring GPS application\n"); if (init_gps() != 0) { printk("init_app fail\n"); } printk("Getting GPS data...\n"); do { /* Loop until we don't have more * data to read */ } while (process_gps_data(&gps_data) > 0); printk("---------------------------------\n"); print_pvt_data(&last_fix); /* If gps data is broken, get it again */ printk("---------------------------------\n"); configure_gps_off_on(GPS_DIS); k_sleep(K_SECONDS(20)); } }
<result> ***** Booting Zephyr OS v1.14.99-ncs2-rc3 ***** The MQTT simple sample started LTE Link Connecting ... LTE Link Connected! IPv4 Address found xxx.xx.xx.xxx [mqtt_evt_handler:389] MQTT client connected! Subscribing to: my/subscribe/topic len 18 Staring GPS application at_commands[0] = AT%XSYSTEMMODE=1,0,1,0 at_commands[1] = AT%XMAGPIO=1,0,0,1,1,1574,1577 at_commands[2] = AT+CFUN=1 at_sock = 4 at_commands[i] = AT%XSYSTEMMODE=1,0,1,0 strlen(at_commands[i]) = 22 buf = ER Error3 Failed to enable GPS init_app fail Getting GPS data... --------------------------------- Longitude: 0.000000 Latitude: 0.000000 Altitude: 0.000000 Speed: 0.000000 Heading: 0.000000 Date: 00-00-00 Time (UTC): 00:00:00 --------------------------------- at_commands[0] = AT%XSYSTEMMODE=1,0,0,0 at_commands[1] = AT%XMAGPIO at_commands[2] = AT+CFUN=1 at_sock = 4 at_commands[i] = AT%XSYSTEMMODE=1,0,0,0 strlen(at_commands[i]) = 22 buf = ER Error3