/* * Copyright (c) 2018 Nordic Semiconductor ASA * Copyright (c) 2024 Conexio Technologies, Inc * * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause */ #include #include #include #include #include #include #include #include /* Header file for the MQTT Library*/ #include #include #include "mqtt_connection.h" /* The mqtt client struct */ static struct mqtt_client client; /* File descriptor */ static struct pollfd fds; /* Define the PVT data frame variable */ static struct nrf_modem_gnss_pvt_data_frame pvt_data; /* Declare helper variables to find the TTFF */ static int64_t gnss_start_time; static bool first_fix = false; static void gnss_event_handler(int event); static void print_fix_data(struct nrf_modem_gnss_pvt_data_frame *pvt_data); static K_SEM_DEFINE(lte_connected, 0, 1); LOG_MODULE_REGISTER(mqtt_app, LOG_LEVEL_INF); static void lte_handler(const struct lte_lc_evt *const evt) { LOG_INF("LTE handler"); 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)) { break; } LOG_INF("Network registration status: %s", evt->nw_reg_status == LTE_LC_NW_REG_REGISTERED_HOME ? "Connected - home network" : "Connected - roaming"); k_sem_give(<e_connected); break; case LTE_LC_EVT_RRC_UPDATE: LOG_INF("RRC mode: %s", evt->rrc_mode == LTE_LC_RRC_MODE_CONNECTED ? "Connected" : "Idle"); break; default: break; } } static int modem_configure(void) { int err; LOG_INF("Initializing modem library"); err = nrf_modem_lib_init(); if (err) { LOG_ERR("Failed to initialize the modem library, error: %d", err); return err; } /* lte_lc_init deprecated in >= v2.6.0 */ #if NCS_VERSION_NUMBER < 0x20600 err = lte_lc_init(); if (err) { LOG_ERR("Failed to initialize LTE link control library, error: %d", err); return err; } #endif LOG_INF("Connecting to LTE network"); err = lte_lc_connect_async(lte_handler); if (err) { LOG_ERR("Error in lte_lc_connect_async, error: %d", err); return err; } k_sem_take(<e_connected, K_FOREVER); LOG_INF("Connected to LTE network"); #if 1 /* Activate only the GNSS stack * / if (lte_lc_func_mode_set(LTE_LC_FUNC_MODE_ACTIVATE_GNSS) != 0) { LOG_ERR("Failed to activate GNSS functional mode"); return 0; } */ /* Register the GNSS event handler */ if (nrf_modem_gnss_event_handler_set(gnss_event_handler) != 0) { LOG_ERR("Failed to set GNSS event handler"); return 0; } /* Set the GNSS fix interval and GNSS fix retry period */ //if (nrf_modem_gnss_fix_interval_set(CONFIG_GNSS_PERIODIC_INTERVAL) != 0) { // LOG_ERR("Failed to set GNSS fix interval"); // return 0; //} //if (nrf_modem_gnss_fix_retry_set(CONFIG_GNSS_PERIODIC_TIMEOUT) != 0) { // LOG_ERR("Failed to set GNSS fix retry"); // return 0; //} /* Start the GNSS receiver */ LOG_INF("Starting GNSS"); if (nrf_modem_gnss_start() != 0) { LOG_ERR("Failed to start GNSS"); return 0; } #endif // Blink LED to indicate we connected to MQTT broker dk_set_led_on(DK_LED1); k_msleep(2000); dk_set_led_off(DK_LED1); return 0; } static void button_handler(uint32_t button_state, uint32_t has_changed) { switch (has_changed) { case DK_BTN1_MSK: /* When button 1/Mode is pressed, call data_publish() to publish a message */ if (button_state & DK_BTN1_MSK){ int err = data_publish(&client, MQTT_QOS_1_AT_LEAST_ONCE, CONFIG_BUTTON_EVENT_PUBLISH_MSG, sizeof(CONFIG_BUTTON_EVENT_PUBLISH_MSG)-1); if (err) { LOG_INF("Failed to send message, %d", err); return; } } break; } } #if 1 /* Define a function to log fix data in a readable format */ static void print_fix_data(struct nrf_modem_gnss_pvt_data_frame *pvt_data) { LOG_INF("Latitude: %.06f", pvt_data->latitude); LOG_INF("Longitude: %.06f", pvt_data->longitude); LOG_INF("Altitude: %.01f m", pvt_data->altitude); LOG_INF("Time (UTC): %02u:%02u:%02u.%03u", pvt_data->datetime.hour, pvt_data->datetime.minute, pvt_data->datetime.seconds, pvt_data->datetime.ms); } static void gnss_event_handler(int event) { int err; switch (event) { /* On a PVT event, confirm if PVT data is a valid fix */ case NRF_MODEM_GNSS_EVT_PVT: LOG_INF("Searching..."); /* Print satellite information */ int num_satellites = 0; for (int i = 0; i < 12 ; i++) { if (pvt_data.sv[i].signal != 0) { LOG_INF("sv: %d, cn0: %d", pvt_data.sv[i].sv, pvt_data.sv[i].cn0); num_satellites++; } } LOG_INF("Number of current satellites: %d", num_satellites); err = nrf_modem_gnss_read(&pvt_data, sizeof(pvt_data), NRF_MODEM_GNSS_DATA_PVT); if (err) { LOG_ERR("nrf_modem_gnss_read failed, err %d", err); return; } if (pvt_data.flags & NRF_MODEM_GNSS_PVT_FLAG_FIX_VALID) { dk_set_led_on(DK_LED1); print_fix_data(&pvt_data); /* Print the time to first fix */ if (!first_fix) { LOG_INF("Time to first fix: %2.1lld s", (k_uptime_get() - gnss_start_time)/1000); first_fix = true; } return; } break; /* Log when the GNSS sleeps and wakes up */ case NRF_MODEM_GNSS_EVT_PERIODIC_WAKEUP: LOG_INF("GNSS has woken up"); break; case NRF_MODEM_GNSS_EVT_SLEEP_AFTER_FIX: LOG_INF("GNSS enter sleep after fix"); break; default: break; } } #endif int main(void) { int err; uint32_t connect_attempt = 0; LOG_INF("Starting MQTT sample on %s\n", CONFIG_BOARD); if (dk_leds_init() != 0) { LOG_ERR("Failed to initialize the LED library"); } err = modem_configure(); if (err) { LOG_ERR("Failed to configure the modem"); return 0; } if (dk_buttons_init(button_handler) != 0) { LOG_ERR("Failed to initialize the buttons library"); } err = client_init(&client); if (err) { LOG_ERR("Failed to initialize MQTT client: %d", err); return 0; } 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)); } LOG_INF("Connection to broker using mqtt_connect"); err = mqtt_connect(&client); if (err) { LOG_ERR("Error in mqtt_connect: %d", err); goto do_connect; } err = fds_init(&client,&fds); if (err) { LOG_ERR("Error in fds_init: %d", err); return 0; } while (1) { err = poll(&fds, 1, mqtt_keepalive_time_left(&client)); if (err < 0) { LOG_ERR("Error in poll(): %d", errno); break; } err = mqtt_live(&client); if ((err != 0) && (err != -EAGAIN)) { LOG_ERR("Error in mqtt_live: %d", err); break; } if ((fds.revents & POLLIN) == POLLIN) { err = mqtt_input(&client); if (err != 0) { LOG_ERR("Error in 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; /* This is never reached */ return 0; }