Hello there,
I tried combining the GNSS simple sample code to my edited version of the MQTT simple sample code and I am unable to build anything. I am getting this error.
( I have configured prj.conf and kconfig files for gnss as well)
/* * Copyright (c) 2018 Nordic Semiconductor ASA * * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause */ #include <zephyr/kernel.h> #include <stdio.h> #include <zephyr/drivers/uart.h> #include <string.h> #include <zephyr/random/rand32.h> #include <zephyr/net/mqtt.h> #include <zephyr/net/socket.h> // frome here: these are modules used for gnss #include <stdlib.h> #include <math.h> #include <nrf_modem_gnss.h> #include <date_time.h> // to here: end #if defined(CONFIG_NRF_MODEM_LIB) #include <nrf_modem_at.h> #endif /* CONFIG_NRF_MODEM_LIB */ #include <modem/lte_lc.h> #include <zephyr/logging/log.h> #if defined(CONFIG_MODEM_KEY_MGMT) #include <modem/modem_key_mgmt.h> #endif #if defined(CONFIG_LWM2M_CARRIER) #include <lwm2m_carrier.h> #endif #include <dk_buttons_and_leds.h> #include "certificates.h" // Start: All of the code below this line is in relation to the GNSS code #define PI 3.14159265358979323846 #define EARTH_RADIUS_METERS (6371.0 * 1000.0) #if !defined(CONFIG_GNSS_SAMPLE_ASSISTANCE_NONE) || defined(CONFIG_GNSS_SAMPLE_MODE_TTFF_TEST) static struct k_work_q gnss_work_q; #define GNSS_WORKQ_THREAD_STACK_SIZE 2304 #define GNSS_WORKQ_THREAD_PRIORITY 5 K_THREAD_STACK_DEFINE(gnss_workq_stack_area, GNSS_WORKQ_THREAD_STACK_SIZE); #endif /* !CONFIG_GNSS_SAMPLE_ASSISTANCE_NONE || CONFIG_GNSS_SAMPLE_MODE_TTFF_TEST */ #if !defined(CONFIG_GNSS_SAMPLE_ASSISTANCE_NONE) #include "assistance.h" static struct nrf_modem_gnss_agps_data_frame last_agps; static struct k_work agps_data_get_work; static volatile bool requesting_assistance; #endif /* !CONFIG_GNSS_SAMPLE_ASSISTANCE_NONE */ #if defined(CONFIG_GNSS_SAMPLE_MODE_TTFF_TEST) static struct k_work_delayable ttff_test_got_fix_work; static struct k_work_delayable ttff_test_prepare_work; static struct k_work ttff_test_start_work; static uint32_t time_to_fix; #endif static const char update_indicator[] = {'\\', '|', '/', '-'}; static struct nrf_modem_gnss_pvt_data_frame last_pvt; static uint64_t fix_timestamp; static uint32_t time_blocked; /* Reference position. */ static bool ref_used; static double ref_latitude; static double ref_longitude; K_MSGQ_DEFINE(nmea_queue, sizeof(struct nrf_modem_gnss_nmea_data_frame *), 10, 4); static K_SEM_DEFINE(pvt_data_sem, 0, 1); static K_SEM_DEFINE(time_sem, 0, 1); static struct k_poll_event events[2] = { K_POLL_EVENT_STATIC_INITIALIZER(K_POLL_TYPE_SEM_AVAILABLE, K_POLL_MODE_NOTIFY_ONLY, &pvt_data_sem, 0), K_POLL_EVENT_STATIC_INITIALIZER(K_POLL_TYPE_MSGQ_DATA_AVAILABLE, K_POLL_MODE_NOTIFY_ONLY, &nmea_queue, 0), }; BUILD_ASSERT(IS_ENABLED(CONFIG_LTE_NETWORK_MODE_LTE_M_GPS) || IS_ENABLED(CONFIG_LTE_NETWORK_MODE_NBIOT_GPS) || IS_ENABLED(CONFIG_LTE_NETWORK_MODE_LTE_M_NBIOT_GPS), "CONFIG_LTE_NETWORK_MODE_LTE_M_GPS, " "CONFIG_LTE_NETWORK_MODE_NBIOT_GPS or " "CONFIG_LTE_NETWORK_MODE_LTE_M_NBIOT_GPS must be enabled"); BUILD_ASSERT((sizeof(CONFIG_GNSS_SAMPLE_REFERENCE_LATITUDE) == 1 && sizeof(CONFIG_GNSS_SAMPLE_REFERENCE_LONGITUDE) == 1) || (sizeof(CONFIG_GNSS_SAMPLE_REFERENCE_LATITUDE) > 1 && sizeof(CONFIG_GNSS_SAMPLE_REFERENCE_LONGITUDE) > 1), "CONFIG_GNSS_SAMPLE_REFERENCE_LATITUDE and " "CONFIG_GNSS_SAMPLE_REFERENCE_LONGITUDE must be both either set or empty"); /* Returns the distance between two coordinates in meters. The distance is calculated using the * haversine formula. */ static double distance_calculate(double lat1, double lon1, double lat2, double lon2) { double d_lat_rad = (lat2 - lat1) * PI / 180.0; double d_lon_rad = (lon2 - lon1) * PI / 180.0; double lat1_rad = lat1 * PI / 180.0; double lat2_rad = lat2 * PI / 180.0; double a = pow(sin(d_lat_rad / 2), 2) + pow(sin(d_lon_rad / 2), 2) * cos(lat1_rad) * cos(lat2_rad); double c = 2 * asin(sqrt(a)); return EARTH_RADIUS_METERS * c; } static void print_distance_from_reference(struct nrf_modem_gnss_pvt_data_frame *pvt_data) { if (!ref_used) { return; } double distance = distance_calculate(pvt_data->latitude, pvt_data->longitude, ref_latitude, ref_longitude); if (IS_ENABLED(CONFIG_GNSS_SAMPLE_MODE_TTFF_TEST)) { LOG_INF("Distance from reference: %.01f", distance); } else { printf("\nDistance from reference: %.01f\n", distance); } } static void gnss_event_handler(int event) { int retval; struct nrf_modem_gnss_nmea_data_frame *nmea_data; switch (event) { case NRF_MODEM_GNSS_EVT_PVT: retval = nrf_modem_gnss_read(&last_pvt, sizeof(last_pvt), NRF_MODEM_GNSS_DATA_PVT); if (retval == 0) { k_sem_give(&pvt_data_sem); } break; #if defined(CONFIG_GNSS_SAMPLE_MODE_TTFF_TEST) case NRF_MODEM_GNSS_EVT_FIX: /* Time to fix is calculated here, but it's printed from a delayed work to avoid * messing up the NMEA output. */ time_to_fix = (k_uptime_get() - fix_timestamp) / 1000; k_work_schedule_for_queue(&gnss_work_q, &ttff_test_got_fix_work, K_MSEC(100)); k_work_schedule_for_queue(&gnss_work_q, &ttff_test_prepare_work, K_SECONDS(CONFIG_GNSS_SAMPLE_MODE_TTFF_TEST_INTERVAL)); break; #endif /* CONFIG_GNSS_SAMPLE_MODE_TTFF_TEST */ case NRF_MODEM_GNSS_EVT_NMEA: nmea_data = k_malloc(sizeof(struct nrf_modem_gnss_nmea_data_frame)); if (nmea_data == NULL) { LOG_ERR("Failed to allocate memory for NMEA"); break; } retval = nrf_modem_gnss_read(nmea_data, sizeof(struct nrf_modem_gnss_nmea_data_frame), NRF_MODEM_GNSS_DATA_NMEA); if (retval == 0) { retval = k_msgq_put(&nmea_queue, &nmea_data, K_NO_WAIT); } if (retval != 0) { k_free(nmea_data); } break; case NRF_MODEM_GNSS_EVT_AGPS_REQ: #if !defined(CONFIG_GNSS_SAMPLE_ASSISTANCE_NONE) retval = nrf_modem_gnss_read(&last_agps, sizeof(last_agps), NRF_MODEM_GNSS_DATA_AGPS_REQ); if (retval == 0) { k_work_submit_to_queue(&gnss_work_q, &agps_data_get_work); } #endif /* !CONFIG_GNSS_SAMPLE_ASSISTANCE_NONE */ break; default: break; } } #if !defined(CONFIG_GNSS_SAMPLE_ASSISTANCE_NONE) #if defined(CONFIG_GNSS_SAMPLE_LTE_ON_DEMAND) K_SEM_DEFINE(lte_ready, 0, 1); static void lte_lc_event_handler(const struct lte_lc_evt *const evt) { switch (evt->type) { case LTE_LC_EVT_NW_REG_STATUS: if ((evt->nw_reg_status == LTE_LC_NW_REG_REGISTERED_HOME) || (evt->nw_reg_status == LTE_LC_NW_REG_REGISTERED_ROAMING)) { LOG_INF("Connected to LTE network"); k_sem_give(<e_ready); } break; default: break; } } void lte_connect(void) { int err; LOG_INF("Connecting to LTE network"); err = lte_lc_func_mode_set(LTE_LC_FUNC_MODE_ACTIVATE_LTE); if (err) { LOG_ERR("Failed to activate LTE, error: %d", err); return; } k_sem_take(<e_ready, K_FOREVER); /* Wait for a while, because with IPv4v6 PDN the IPv6 activation takes a bit more time. */ k_sleep(K_SECONDS(1)); } void lte_disconnect(void) { int err; err = lte_lc_func_mode_set(LTE_LC_FUNC_MODE_DEACTIVATE_LTE); if (err) { LOG_ERR("Failed to deactivate LTE, error: %d", err); return; } LOG_INF("LTE disconnected"); } #endif /* CONFIG_GNSS_SAMPLE_LTE_ON_DEMAND */ static void agps_data_get_work_fn(struct k_work *item) { ARG_UNUSED(item); int err; #if defined(CONFIG_GNSS_SAMPLE_ASSISTANCE_SUPL) /* SUPL doesn't usually provide satellite real time integrity information. If GNSS asks * only for satellite integrity, the request should be ignored. */ if (last_agps.sv_mask_ephe == 0 && last_agps.sv_mask_alm == 0 && last_agps.data_flags == NRF_MODEM_GNSS_AGPS_INTEGRITY_REQUEST) { LOG_INF("Ignoring assistance request for only satellite integrity"); return; } #endif /* CONFIG_GNSS_SAMPLE_ASSISTANCE_SUPL */ #if defined(CONFIG_GNSS_SAMPLE_ASSISTANCE_MINIMAL) /* With minimal assistance, the request should be ignored if no GPS time or position * is requested. */ if (!(last_agps.data_flags & NRF_MODEM_GNSS_AGPS_SYS_TIME_AND_SV_TOW_REQUEST) && !(last_agps.data_flags & NRF_MODEM_GNSS_AGPS_POSITION_REQUEST)) { LOG_INF("Ignoring assistance request because no GPS time or position is requested"); return; } #endif /* CONFIG_GNSS_SAMPLE_ASSISTANCE_MINIMAL */ requesting_assistance = true; LOG_INF("Assistance data needed, ephe 0x%08x, alm 0x%08x, flags 0x%02x", last_agps.sv_mask_ephe, last_agps.sv_mask_alm, last_agps.data_flags); #if defined(CONFIG_GNSS_SAMPLE_LTE_ON_DEMAND) lte_connect(); #endif /* CONFIG_GNSS_SAMPLE_LTE_ON_DEMAND */ err = assistance_request(&last_agps); if (err) { LOG_ERR("Failed to request assistance data"); } #if defined(CONFIG_GNSS_SAMPLE_LTE_ON_DEMAND) lte_disconnect(); #endif /* CONFIG_GNSS_SAMPLE_LTE_ON_DEMAND */ requesting_assistance = false; } #endif /* !CONFIG_GNSS_SAMPLE_ASSISTANCE_NONE */ #if defined(CONFIG_GNSS_SAMPLE_MODE_TTFF_TEST) static void ttff_test_got_fix_work_fn(struct k_work *item) { LOG_INF("Time to fix: %u", time_to_fix); if (time_blocked > 0) { LOG_INF("Time GNSS was blocked by LTE: %u", time_blocked); } print_distance_from_reference(&last_pvt); LOG_INF("Sleeping for %u seconds", CONFIG_GNSS_SAMPLE_MODE_TTFF_TEST_INTERVAL); } static int ttff_test_force_cold_start(void) { int err; uint32_t delete_mask; LOG_INF("Deleting GNSS data"); /* Delete everything else except the TCXO offset. */ delete_mask = NRF_MODEM_GNSS_DELETE_EPHEMERIDES | NRF_MODEM_GNSS_DELETE_ALMANACS | NRF_MODEM_GNSS_DELETE_IONO_CORRECTION_DATA | NRF_MODEM_GNSS_DELETE_LAST_GOOD_FIX | NRF_MODEM_GNSS_DELETE_GPS_TOW | NRF_MODEM_GNSS_DELETE_GPS_WEEK | NRF_MODEM_GNSS_DELETE_UTC_DATA | NRF_MODEM_GNSS_DELETE_GPS_TOW_PRECISION; /* With minimal assistance, we want to keep the factory almanac. */ if (IS_ENABLED(CONFIG_GNSS_SAMPLE_ASSISTANCE_MINIMAL)) { delete_mask &= ~NRF_MODEM_GNSS_DELETE_ALMANACS; } err = nrf_modem_gnss_nv_data_delete(delete_mask); if (err) { LOG_ERR("Failed to delete GNSS data"); return -1; } return 0; } static void ttff_test_prepare_work_fn(struct k_work *item) { /* Make sure GNSS is stopped before next start. */ nrf_modem_gnss_stop(); if (IS_ENABLED(CONFIG_GNSS_SAMPLE_MODE_TTFF_TEST_COLD_START)) { if (ttff_test_force_cold_start() != 0) { return; } } #if !defined(CONFIG_GNSS_SAMPLE_ASSISTANCE_NONE) if (IS_ENABLED(CONFIG_GNSS_SAMPLE_MODE_TTFF_TEST_COLD_START)) { /* All A-GPS data is always requested before GNSS is started. */ last_agps.sv_mask_ephe = 0xffffffff; last_agps.sv_mask_alm = 0xffffffff; last_agps.data_flags = NRF_MODEM_GNSS_AGPS_GPS_UTC_REQUEST | NRF_MODEM_GNSS_AGPS_KLOBUCHAR_REQUEST | NRF_MODEM_GNSS_AGPS_SYS_TIME_AND_SV_TOW_REQUEST | NRF_MODEM_GNSS_AGPS_POSITION_REQUEST | NRF_MODEM_GNSS_AGPS_INTEGRITY_REQUEST; k_work_submit_to_queue(&gnss_work_q, &agps_data_get_work); } else { /* Start and stop GNSS to trigger possible A-GPS data request. If new A-GPS * data is needed it is fetched before GNSS is started. */ nrf_modem_gnss_start(); nrf_modem_gnss_stop(); } #endif /* !CONFIG_GNSS_SAMPLE_ASSISTANCE_NONE */ k_work_submit_to_queue(&gnss_work_q, &ttff_test_start_work); } static void ttff_test_start_work_fn(struct k_work *item) { LOG_INF("Starting GNSS"); if (nrf_modem_gnss_start() != 0) { LOG_ERR("Failed to start GNSS"); return; } fix_timestamp = k_uptime_get(); time_blocked = 0; } #endif /* CONFIG_GNSS_SAMPLE_MODE_TTFF_TEST */ static void date_time_evt_handler(const struct date_time_evt *evt) { k_sem_give(&time_sem); } static int modem_init(void) { if (IS_ENABLED(CONFIG_DATE_TIME)) { date_time_register_handler(date_time_evt_handler); } if (lte_lc_init() != 0) { LOG_ERR("Failed to initialize LTE link controller"); return -1; } #if defined(CONFIG_GNSS_SAMPLE_LTE_ON_DEMAND) lte_lc_register_handler(lte_lc_event_handler); #elif !defined(CONFIG_GNSS_SAMPLE_ASSISTANCE_NONE) lte_lc_psm_req(true); LOG_INF("Connecting to LTE network"); if (lte_lc_connect() != 0) { LOG_ERR("Failed to connect to LTE network"); return -1; } LOG_INF("Connected to LTE network"); if (IS_ENABLED(CONFIG_DATE_TIME)) { LOG_INF("Waiting for current time"); /* Wait for an event from the Date Time library. */ k_sem_take(&time_sem, K_MINUTES(10)); if (!date_time_is_valid()) { LOG_WRN("Failed to get current time, continuing anyway"); } } #endif return 0; } static int sample_init(void) { int err = 0; #if !defined(CONFIG_GNSS_SAMPLE_ASSISTANCE_NONE) || defined(CONFIG_GNSS_SAMPLE_MODE_TTFF_TEST) struct k_work_queue_config cfg = { .name = "gnss_work_q", .no_yield = false}; k_work_queue_start( &gnss_work_q, gnss_workq_stack_area, K_THREAD_STACK_SIZEOF(gnss_workq_stack_area), GNSS_WORKQ_THREAD_PRIORITY, &cfg); #endif /* !CONFIG_GNSS_SAMPLE_ASSISTANCE_NONE || CONFIG_GNSS_SAMPLE_MODE_TTFF_TEST */ #if !defined(CONFIG_GNSS_SAMPLE_ASSISTANCE_NONE) k_work_init(&agps_data_get_work, agps_data_get_work_fn); err = assistance_init(&gnss_work_q); #endif /* !CONFIG_GNSS_SAMPLE_ASSISTANCE_NONE */ #if defined(CONFIG_GNSS_SAMPLE_MODE_TTFF_TEST) k_work_init_delayable(&ttff_test_got_fix_work, ttff_test_got_fix_work_fn); k_work_init_delayable(&ttff_test_prepare_work, ttff_test_prepare_work_fn); k_work_init(&ttff_test_start_work, ttff_test_start_work_fn); #endif /* CONFIG_GNSS_SAMPLE_MODE_TTFF_TEST */ return err; } static int gnss_init_and_start(void) { #if defined(CONFIG_GNSS_SAMPLE_ASSISTANCE_NONE) || defined(CONFIG_GNSS_SAMPLE_LTE_ON_DEMAND) /* Enable GNSS. */ if (lte_lc_func_mode_set(LTE_LC_FUNC_MODE_ACTIVATE_GNSS) != 0) { LOG_ERR("Failed to activate GNSS functional mode"); return -1; } #endif /* CONFIG_GNSS_SAMPLE_ASSISTANCE_NONE || CONFIG_GNSS_SAMPLE_LTE_ON_DEMAND */ /* Configure GNSS. */ if (nrf_modem_gnss_event_handler_set(gnss_event_handler) != 0) { LOG_ERR("Failed to set GNSS event handler"); return -1; } /* Enable all supported NMEA messages. */ uint16_t nmea_mask = NRF_MODEM_GNSS_NMEA_RMC_MASK | NRF_MODEM_GNSS_NMEA_GGA_MASK | NRF_MODEM_GNSS_NMEA_GLL_MASK | NRF_MODEM_GNSS_NMEA_GSA_MASK | NRF_MODEM_GNSS_NMEA_GSV_MASK; if (nrf_modem_gnss_nmea_mask_set(nmea_mask) != 0) { LOG_ERR("Failed to set GNSS NMEA mask"); return -1; } /* This use case flag should always be set. */ uint8_t use_case = NRF_MODEM_GNSS_USE_CASE_MULTIPLE_HOT_START; if (IS_ENABLED(CONFIG_GNSS_SAMPLE_MODE_PERIODIC) && !IS_ENABLED(CONFIG_GNSS_SAMPLE_ASSISTANCE_NONE)) { /* Disable GNSS scheduled downloads when assistance is used. */ use_case |= NRF_MODEM_GNSS_USE_CASE_SCHED_DOWNLOAD_DISABLE; } if (IS_ENABLED(CONFIG_GNSS_SAMPLE_LOW_ACCURACY)) { use_case |= NRF_MODEM_GNSS_USE_CASE_LOW_ACCURACY; } if (nrf_modem_gnss_use_case_set(use_case) != 0) { LOG_WRN("Failed to set GNSS use case"); } #if defined(CONFIG_NRF_CLOUD_AGPS_ELEVATION_MASK) if (nrf_modem_gnss_elevation_threshold_set(CONFIG_NRF_CLOUD_AGPS_ELEVATION_MASK) != 0) { LOG_ERR("Failed to set elevation threshold"); return -1; } LOG_DBG("Set elevation threshold to %u", CONFIG_NRF_CLOUD_AGPS_ELEVATION_MASK); #endif #if defined(CONFIG_GNSS_SAMPLE_MODE_CONTINUOUS) /* Default to no power saving. */ uint8_t power_mode = NRF_MODEM_GNSS_PSM_DISABLED; #if defined(GNSS_SAMPLE_POWER_SAVING_MODERATE) power_mode = NRF_MODEM_GNSS_PSM_DUTY_CYCLING_PERFORMANCE; #elif defined(GNSS_SAMPLE_POWER_SAVING_HIGH) power_mode = NRF_MODEM_GNSS_PSM_DUTY_CYCLING_POWER; #endif if (nrf_modem_gnss_power_mode_set(power_mode) != 0) { LOG_ERR("Failed to set GNSS power saving mode"); return -1; } #endif /* CONFIG_GNSS_SAMPLE_MODE_CONTINUOUS */ /* Default to continuous tracking. */ uint16_t fix_retry = 0; uint16_t fix_interval = 1; #if defined(CONFIG_GNSS_SAMPLE_MODE_PERIODIC) fix_retry = CONFIG_GNSS_SAMPLE_PERIODIC_TIMEOUT; fix_interval = CONFIG_GNSS_SAMPLE_PERIODIC_INTERVAL; #elif defined(CONFIG_GNSS_SAMPLE_MODE_TTFF_TEST) /* Single fix for TTFF test mode. */ fix_retry = 0; fix_interval = 0; #endif if (nrf_modem_gnss_fix_retry_set(fix_retry) != 0) { LOG_ERR("Failed to set GNSS fix retry"); return -1; } if (nrf_modem_gnss_fix_interval_set(fix_interval) != 0) { LOG_ERR("Failed to set GNSS fix interval"); return -1; } #if defined(CONFIG_GNSS_SAMPLE_MODE_TTFF_TEST) k_work_schedule_for_queue(&gnss_work_q, &ttff_test_prepare_work, K_NO_WAIT); #else /* !CONFIG_GNSS_SAMPLE_MODE_TTFF_TEST */ if (nrf_modem_gnss_start() != 0) { LOG_ERR("Failed to start GNSS"); return -1; } #endif return 0; } static bool output_paused(void) { #if defined(CONFIG_GNSS_SAMPLE_ASSISTANCE_NONE) || defined(CONFIG_GNSS_SAMPLE_LOG_LEVEL_OFF) return false; #else return (requesting_assistance || assistance_is_active()) ? true : false; #endif } static void print_satellite_stats(struct nrf_modem_gnss_pvt_data_frame *pvt_data) { uint8_t tracked = 0; uint8_t in_fix = 0; uint8_t unhealthy = 0; for (int i = 0; i < NRF_MODEM_GNSS_MAX_SATELLITES; ++i) { if (pvt_data->sv[i].sv > 0) { tracked++; if (pvt_data->sv[i].flags & NRF_MODEM_GNSS_SV_FLAG_USED_IN_FIX) { in_fix++; } if (pvt_data->sv[i].flags & NRF_MODEM_GNSS_SV_FLAG_UNHEALTHY) { unhealthy++; } } } printf("Tracking: %2d Using: %2d Unhealthy: %d\n", tracked, in_fix, unhealthy); } static void print_fix_data(struct nrf_modem_gnss_pvt_data_frame *pvt_data) { printf("Latitude: %.06f\n", pvt_data->latitude); printf("Longitude: %.06f\n", pvt_data->longitude); printf("Altitude: %.01f m\n", pvt_data->altitude); printf("Accuracy: %.01f m\n", pvt_data->accuracy); printf("Speed: %.01f m/s\n", pvt_data->speed); printf("Speed accuracy: %.01f m/s\n", pvt_data->speed_accuracy); printf("Heading: %.01f deg\n", pvt_data->heading); printf("Date: %04u-%02u-%02u\n", pvt_data->datetime.year, pvt_data->datetime.month, pvt_data->datetime.day); printf("Time (UTC): %02u:%02u:%02u.%03u\n", pvt_data->datetime.hour, pvt_data->datetime.minute, pvt_data->datetime.seconds, pvt_data->datetime.ms); printf("PDOP: %.01f\n", pvt_data->pdop); printf("HDOP: %.01f\n", pvt_data->hdop); printf("VDOP: %.01f\n", pvt_data->vdop); printf("TDOP: %.01f\n", pvt_data->tdop); } // STOP: this is the end of the GNSS code functions that I have transferred LOG_MODULE_REGISTER(mqtt_simple, CONFIG_MQTT_SIMPLE_LOG_LEVEL); /* Buffers for MQTT client. */ static uint8_t rx_buffer[CONFIG_MQTT_MESSAGE_BUFFER_SIZE]; static uint8_t tx_buffer[CONFIG_MQTT_MESSAGE_BUFFER_SIZE]; static uint8_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; /* File descriptor */ static struct pollfd fds; #if defined(CONFIG_MQTT_LIB_TLS) // Not being called static int certificates_provision(void) { int err = 0; LOG_INF("Provisioning certificates"); #if defined(CONFIG_NRF_MODEM_LIB) && defined(CONFIG_MODEM_KEY_MGMT) err = modem_key_mgmt_write(CONFIG_MQTT_TLS_SEC_TAG, MODEM_KEY_MGMT_CRED_TYPE_CA_CHAIN, CA_CERTIFICATE, strlen(CA_CERTIFICATE)); if (err) { LOG_ERR("Failed to provision CA certificate: %d", err); return err; } #elif defined(CONFIG_BOARD_QEMU_X86) && defined(CONFIG_NET_SOCKETS_SOCKOPT_TLS) err = tls_credential_add(CONFIG_MQTT_TLS_SEC_TAG, TLS_CREDENTIAL_CA_CERTIFICATE, CA_CERTIFICATE, sizeof(CA_CERTIFICATE)); if (err) { LOG_ERR("Failed to register CA certificate: %d", err); return err; } #endif return err; } #endif /* defined(CONFIG_MQTT_LIB_TLS) */ #if defined(CONFIG_LWM2M_CARRIER) K_SEM_DEFINE(carrier_registered, 0, 1); int lwm2m_carrier_event_handler(const lwm2m_carrier_event_t *event) { switch (event->type) { case LWM2M_CARRIER_EVENT_BSDLIB_INIT: LOG_INF("LWM2M_CARRIER_EVENT_BSDLIB_INIT"); break; case LWM2M_CARRIER_EVENT_CONNECTING: LOG_INF("LWM2M_CARRIER_EVENT_CONNECTING"); break; case LWM2M_CARRIER_EVENT_CONNECTED: LOG_INF("LWM2M_CARRIER_EVENT_CONNECTED"); break; case LWM2M_CARRIER_EVENT_DISCONNECTING: LOG_INF("LWM2M_CARRIER_EVENT_DISCONNECTING"); break; case LWM2M_CARRIER_EVENT_DISCONNECTED: LOG_INF("LWM2M_CARRIER_EVENT_DISCONNECTED"); break; case LWM2M_CARRIER_EVENT_BOOTSTRAPPED: LOG_INF("LWM2M_CARRIER_EVENT_BOOTSTRAPPED"); break; case LWM2M_CARRIER_EVENT_REGISTERED: LOG_INF("LWM2M_CARRIER_EVENT_REGISTERED"); k_sem_give(&carrier_registered); break; case LWM2M_CARRIER_EVENT_DEFERRED: LOG_INF("LWM2M_CARRIER_EVENT_DEFERRED"); break; case LWM2M_CARRIER_EVENT_FOTA_START: LOG_INF("LWM2M_CARRIER_EVENT_FOTA_START"); break; case LWM2M_CARRIER_EVENT_REBOOT: LOG_INF("LWM2M_CARRIER_EVENT_REBOOT"); break; case LWM2M_CARRIER_EVENT_ERROR: LOG_ERR("LWM2M_CARRIER_EVENT_ERROR: code %d, value %d", ((lwm2m_carrier_event_error_t *)event->data)->code, ((lwm2m_carrier_event_error_t *)event->data)->value); break; default: LOG_WRN("Unhandled LWM2M_CARRIER_EVENT: %d", event->type); break; } return 0; } #endif /* defined(CONFIG_LWM2M_CARRIER) */ /**@brief Function to print strings without null-termination */ static void data_print(uint8_t *prefix, uint8_t *data, size_t len) { char buf[len + 1]; memcpy(buf, data, len); buf[len] = 0; LOG_INF("%s%s", (char *)prefix, (char *)buf); } /**@brief Function to publish data on the configured topic */ static int data_publish(struct mqtt_client *c, enum mqtt_qos qos, uint8_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); LOG_INF("to topic: %s len: %u", 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}; LOG_INF("Subscribing to: %s len %u", 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) { int ret; int err = 0; /* Return an error if the payload is larger than the payload buffer. * Note: To allow new messages, we have to read the payload before returning. */ if (length > sizeof(payload_buf)) { err = -EMSGSIZE; } /* Truncate payload until it fits in the payload buffer. */ while (length > sizeof(payload_buf)) { ret = mqtt_read_publish_payload_blocking( c, payload_buf, (length - sizeof(payload_buf))); if (ret == 0) { return -EIO; } else if (ret < 0) { return ret; } length -= ret; } ret = mqtt_readall_publish_payload(c, payload_buf, length); if (ret) { return ret; } return err; } /**@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) { LOG_ERR("MQTT connect failed: %d", evt->result); break; } LOG_INF("MQTT client connected"); subscribe(); break; case MQTT_EVT_DISCONNECT: LOG_INF("MQTT client disconnected: %d", evt->result); break; case MQTT_EVT_PUBLISH: { const struct mqtt_publish_param *p = &evt->param.publish; LOG_INF("MQTT PUBLISH result=%d len=%d", evt->result, p->message.payload.len); err = publish_get_payload(c, p->message.payload.len); if (p->message.topic.qos == MQTT_QOS_1_AT_LEAST_ONCE) { const struct mqtt_puback_param ack = { .message_id = p->message_id}; /* Send acknowledgment. */ mqtt_publish_qos1_ack(&client, &ack); } if (err >= 0) { data_print("Received: ", payload_buf, p->message.payload.len); /* Echo back received data */ // Commented this out because it kept echoing back recieved data // data_publish(&client, MQTT_QOS_1_AT_LEAST_ONCE, // payload_buf, p->message.payload.len); } else if (err == -EMSGSIZE) { LOG_ERR("Received payload (%d bytes) is larger than the payload buffer " "size (%d bytes).", p->message.payload.len, sizeof(payload_buf)); } else { LOG_ERR("publish_get_payload failed: %d", err); LOG_INF("Disconnecting MQTT client..."); err = mqtt_disconnect(c); if (err) { LOG_ERR("Could not disconnect: %d", err); } } } break; case MQTT_EVT_PUBACK: if (evt->result != 0) { LOG_ERR("MQTT PUBACK error: %d", evt->result); break; } LOG_INF("PUBACK packet id: %u", evt->param.puback.message_id); break; case MQTT_EVT_SUBACK: if (evt->result != 0) { LOG_ERR("MQTT SUBACK error: %d", evt->result); break; } LOG_INF("SUBACK packet id: %u", evt->param.suback.message_id); break; case MQTT_EVT_PINGRESP: if (evt->result != 0) { LOG_ERR("MQTT PINGRESP error: %d", evt->result); } break; default: LOG_INF("Unhandled MQTT event type: %d", evt->type); break; } } /**@brief Resolves the configured hostname and * initializes the MQTT broker structure */ static int 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); // to change CONFIG_MQTT_BROKER_HOSTNAME go to kconfig if (err) { LOG_ERR("getaddrinfo failed: %d", err); return -ECHILD; } addr = result; /* 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)); LOG_INF("IPv4 Address found %s", ipv4_addr); break; } else { LOG_ERR("ai_addrlen = %u should be %u or %u", (unsigned int)addr->ai_addrlen, (unsigned int)sizeof(struct sockaddr_in), (unsigned int)sizeof(struct sockaddr_in6)); } addr = addr->ai_next; } /* Free the address. */ freeaddrinfo(result); return err; } #if defined(CONFIG_NRF_MODEM_LIB) #define IMEI_LEN 15 #define CGSN_RESPONSE_LENGTH (IMEI_LEN + 6 + 1) /* Add 6 for \r\nOK\r\n and 1 for \0 */ #define CLIENT_ID_LEN sizeof("nrf-") + IMEI_LEN #else #define RANDOM_LEN 10 #define CLIENT_ID_LEN sizeof(CONFIG_BOARD) + 1 + RANDOM_LEN #endif /* defined(CONFIG_NRF_MODEM_LIB) */ /* Function to get the client id */ static const uint8_t *client_id_get(void) { static uint8_t client_id[MAX(sizeof(CONFIG_MQTT_CLIENT_ID), CLIENT_ID_LEN)]; if (strlen(CONFIG_MQTT_CLIENT_ID) > 0) { snprintf(client_id, sizeof(client_id), "%s", CONFIG_MQTT_CLIENT_ID); goto exit; } #if defined(CONFIG_NRF_MODEM_LIB) char imei_buf[CGSN_RESPONSE_LENGTH + 1]; int err; err = nrf_modem_at_cmd(imei_buf, sizeof(imei_buf), "AT+CGSN"); if (err) { LOG_ERR("Failed to obtain IMEI, error: %d", err); goto exit; } imei_buf[IMEI_LEN] = '\0'; snprintf(client_id, sizeof(client_id), "nrf-%.*s", IMEI_LEN, imei_buf); #else uint32_t id = sys_rand32_get(); snprintf(client_id, sizeof(client_id), "%s-%010u", CONFIG_BOARD, id); #endif /* !defined(NRF_CLOUD_CLIENT_ID) */ exit: LOG_DBG("client_id = %s", (char *)client_id); return client_id; } /**@brief Initialize the MQTT client structure */ static int client_init(struct mqtt_client *client) { int err; mqtt_client_init(client); err = broker_init(); if (err) { LOG_ERR("Failed to initialize broker connection"); return err; } /* MQTT client configuration */ client->broker = &broker; client->evt_cb = mqtt_evt_handler; client->client_id.utf8 = client_id_get(); client->client_id.size = strlen(client->client_id.utf8); client->password = NULL; client->user_name = NULL; 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 */ #if defined(CONFIG_MQTT_LIB_TLS) struct mqtt_sec_config *tls_cfg = &(client->transport).tls.config; static sec_tag_t sec_tag_list[] = {CONFIG_MQTT_TLS_SEC_TAG}; LOG_INF("TLS enabled"); client->transport.type = MQTT_TRANSPORT_SECURE; tls_cfg->peer_verify = CONFIG_MQTT_TLS_PEER_VERIFY; tls_cfg->cipher_count = 0; tls_cfg->cipher_list = NULL; tls_cfg->sec_tag_count = ARRAY_SIZE(sec_tag_list); tls_cfg->sec_tag_list = sec_tag_list; tls_cfg->hostname = CONFIG_MQTT_BROKER_HOSTNAME; #if defined(CONFIG_NRF_MODEM_LIB) tls_cfg->session_cache = IS_ENABLED(CONFIG_MQTT_TLS_SESSION_CACHING) ? TLS_SESSION_CACHE_ENABLED : TLS_SESSION_CACHE_DISABLED; #else /* TLS session caching is not supported by the Zephyr network stack */ tls_cfg->session_cache = TLS_SESSION_CACHE_DISABLED; #endif #else client->transport.type = MQTT_TRANSPORT_NON_SECURE; #endif return err; } /**@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; } #if defined(CONFIG_DK_LIBRARY) static void button_handler(uint32_t button_states, uint32_t has_changed) { if (has_changed & button_states & BIT(CONFIG_BUTTON_EVENT_BTN_NUM - 1)) { int ret; ret = data_publish(&client, MQTT_QOS_1_AT_LEAST_ONCE, CONFIG_BUTTON_EVENT_PUBLISH_MSG, sizeof(CONFIG_BUTTON_EVENT_PUBLISH_MSG) - 1); if (ret) { LOG_ERR("Publish failed: %d", ret); } } } #endif /**@brief Configures modem to provide LTE link. Blocks until link is * successfully established. */ static int modem_configure(void) { #if defined(CONFIG_LTE_LINK_CONTROL) /* Turn off LTE power saving features for a more responsive demo. Also, * request power saving features before network registration. Some * networks rejects timer updates after the device has registered to the * LTE network. */ LOG_INF("Disabling PSM and eDRX"); lte_lc_psm_req(false); lte_lc_edrx_req(false); if (IS_ENABLED(CONFIG_LTE_AUTO_INIT_AND_CONNECT)) { /* Do nothing, modem is already turned on * and connected. */ } else { #if defined(CONFIG_LWM2M_CARRIER) /* Wait for the LWM2M_CARRIER to configure the modem and * start the connection. */ LOG_INF("Waitng for carrier registration..."); k_sem_take(&carrier_registered, K_FOREVER); LOG_INF("Registered!"); #else /* defined(CONFIG_LWM2M_CARRIER) */ int err; LOG_INF("LTE Link Connecting..."); err = lte_lc_init_and_connect(); if (err) { LOG_INF("Failed to establish LTE connection: %d", err); return err; } LOG_INF("LTE Link Connected!"); #endif /* defined(CONFIG_LWM2M_CARRIER) */ } #endif /* defined(CONFIG_LTE_LINK_CONTROL) */ return 0; } ////////////// it all starts here ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// int main(void) { int err; uint32_t connect_attempt = 0; // start: GNSS stuff//////////////////////////////////////////////////// uint8_t cnt = 0; struct nrf_modem_gnss_nmea_data_frame *nmea_data; /* Initialize reference coordinates (if used). */ if (sizeof(CONFIG_GNSS_SAMPLE_REFERENCE_LATITUDE) > 1 && sizeof(CONFIG_GNSS_SAMPLE_REFERENCE_LONGITUDE) > 1) { ref_used = true; ref_latitude = atof(CONFIG_GNSS_SAMPLE_REFERENCE_LATITUDE); ref_longitude = atof(CONFIG_GNSS_SAMPLE_REFERENCE_LONGITUDE); } if (modem_init() != 0) { LOG_ERR("Failed to initialize modem"); return -1; } if (sample_init() != 0) { LOG_ERR("Failed to initialize sample"); return -1; } if (gnss_init_and_start() != 0) { LOG_ERR("Failed to initialize and start GNSS"); return -1; } fix_timestamp = k_uptime_get(); // end: GNSS stuff////////////////////////////////////////////////////// LOG_INF("The MQTT and GNSS code is starting."); #if defined(CONFIG_MQTT_LIB_TLS) err = certificates_provision(); if (err != 0) { LOG_ERR("Failed to provision certificates"); return; } #endif /* defined(CONFIG_MQTT_LIB_TLS) */ do { err = modem_configure(); if (err) { LOG_INF("Retrying in %d seconds", CONFIG_LTE_CONNECT_RETRY_DELAY_S); k_sleep(K_SECONDS(CONFIG_LTE_CONNECT_RETRY_DELAY_S)); } } while (err); err = client_init(&client); if (err != 0) { LOG_ERR("client_init: %d", err); return; } #if defined(CONFIG_DK_LIBRARY) dk_buttons_init(button_handler); #endif do_connect: if (connect_attempt++ > 0) { LOG_INF("Reconnecting in %d seconds...", CONFIG_MQTT_RECONNECT_DELAY_S); k_sleep(K_SECONDS(CONFIG_MQTT_RECONNECT_DELAY_S)); } err = mqtt_connect(&client); if (err != 0) { LOG_ERR("mqtt_connect %d", err); goto do_connect; } err = fds_init(&client); if (err != 0) { LOG_ERR("fds_init: %d", err); return; } while (1) { // start: GNSS stuff//////////////////////////////////////////////////////////// while ((((uint32_t)(k_uptime_get()) / 1000) % 10) == 0) { printf("timer: %d\n", (int)(k_uptime_get()) / 1000); (void)k_poll(events, 2, K_FOREVER); if (events[0].state == K_POLL_STATE_SEM_AVAILABLE && k_sem_take(events[0].sem, K_NO_WAIT) == 0) { /* New PVT data available */ if (IS_ENABLED(CONFIG_GNSS_SAMPLE_MODE_TTFF_TEST)) { /* TTFF test mode. */ /* Calculate the time GNSS has been blocked by LTE. */ if (last_pvt.flags & NRF_MODEM_GNSS_PVT_FLAG_DEADLINE_MISSED) { time_blocked++; } } else if (IS_ENABLED(CONFIG_GNSS_SAMPLE_NMEA_ONLY)) { /* NMEA-only output mode. */ if (output_paused()) { goto handle_nmea; } if (last_pvt.flags & NRF_MODEM_GNSS_PVT_FLAG_FIX_VALID) { print_distance_from_reference(&last_pvt); } } else { /* PVT and NMEA output mode. */ if (output_paused()) { goto handle_nmea; } printf("\033[1;1H"); printf("\033[2J"); print_satellite_stats(&last_pvt); if (last_pvt.flags & NRF_MODEM_GNSS_PVT_FLAG_DEADLINE_MISSED) { printf("GNSS operation blocked by LTE\n"); } if (last_pvt.flags & NRF_MODEM_GNSS_PVT_FLAG_NOT_ENOUGH_WINDOW_TIME) { printf("Insufficient GNSS time windows\n"); } if (last_pvt.flags & NRF_MODEM_GNSS_PVT_FLAG_SLEEP_BETWEEN_PVT) { printf("Sleep period(s) between PVT notifications\n"); } printf("-----------------------------------\n"); if (last_pvt.flags & NRF_MODEM_GNSS_PVT_FLAG_FIX_VALID) { fix_timestamp = k_uptime_get(); print_fix_data(&last_pvt); print_distance_from_reference(&last_pvt); } else { printf("Seconds since last fix: %d\n", (uint32_t)((k_uptime_get() - fix_timestamp) / 1000)); printf("fix_timestamp: %d \n", ((uint32_t)(k_uptime_get()) / 1000) % 10); cnt++; printf("Searching [%c]\n", update_indicator[cnt % 4]); } printf("\nNMEA strings:\n\n"); } } handle_nmea: if (events[1].state == K_POLL_STATE_MSGQ_DATA_AVAILABLE && k_msgq_get(events[1].msgq, &nmea_data, K_NO_WAIT) == 0) { /* New NMEA data available */ if (!output_paused()) { printf("%s", nmea_data->nmea_str); } k_free(nmea_data); } events[0].state = K_POLL_STATE_NOT_READY; events[1].state = K_POLL_STATE_NOT_READY; } // end: GNSS stuff///////////////////////////////////////////// err = poll(&fds, 1, mqtt_keepalive_time_left(&client)); if (err < 0) { LOG_ERR("poll: %d", errno); break; } err = mqtt_live(&client); if ((err != 0) && (err != -EAGAIN)) { LOG_ERR("ERROR: mqtt_live: %d", err); break; } if ((fds.revents & POLLIN) == POLLIN) { err = mqtt_input(&client); if (err != 0) { LOG_ERR("mqtt_input: %d", err); break; } } if ((fds.revents & POLLERR) == POLLERR) { LOG_ERR("POLLERR"); break; } if ((fds.revents & POLLNVAL) == POLLNVAL) { LOG_ERR("POLLNVAL"); break; } } LOG_INF("Disconnecting MQTT client..."); err = mqtt_disconnect(&client); if (err) { LOG_ERR("Could not disconnect MQTT client: %d", err); } goto do_connect; }