diff --git a/CMakeLists.txt b/CMakeLists.txt index 19d6f3a..5818245 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -87,3 +87,31 @@ if (COPY_PREBUILDS) file(COPY_FILE ${CMAKE_BINARY_DIR}/zephyr/merged.hex ${CMAKE_BINARY_DIR}/../prebuild/${BOARD}_full.hex) file(COPY_FILE ${CMAKE_BINARY_DIR}/zephyr/app_signed.hex ${CMAKE_BINARY_DIR}/../prebuild/${BOARD}_app_signed.hex) endif() + +if (CONFIG_COAP_SEND_INTERVAL) +set(BUILD_SUMUP1 "Build with send interval ${CONFIG_COAP_SEND_INTERVAL} s.") +elseif (CONFIG_COAP_WAKEUP_SEND_INTERVAL) +set(BUILD_SUMUP1 "Build with wakeup send interval ${CONFIG_COAP_WAKEUP_SEND_INTERVAL} s.") +else() +set(BUILD_SUMUP1 "Build without send interval.") +endif() + +if (CONFIG_LOCATION_ENABLE) +set(BUILD_SUMUP2 "Build with GNSS.") +else() +set(BUILD_SUMUP2 "Build without GNSS.") +endif() + +if (CONFIG_BME680) +set(BUILD_SUMUP3 "Build with BME680.") +elseif (CONFIG_BME680_BSEC) +set(BUILD_SUMUP3 "Build with BME680 BSEC.") +else() +set(BUILD_SUMUP3 "Build without BME680.") +endif() + +add_custom_command(TARGET app POST_BUILD + COMMAND echo "${BUILD_SUMUP1}" + COMMAND echo "${BUILD_SUMUP2}" + COMMAND echo "${BUILD_SUMUP3}" + ) diff --git a/Kconfig b/Kconfig index 1b4734d..1da6308 100644 --- a/Kconfig +++ b/Kconfig @@ -14,29 +14,52 @@ menu "CoAP tinyDTLS Settings" config COAP_SERVER_HOSTNAME - string "CoAP server hostname" + string "CoAP server hostname." default "californium.eclipseprojects.io" config COAP_SERVER_ADDRESS_STATIC - string "CoAP server IP address (alternative, if DNS is not available)" + string "CoAP server IP address (alternative, if DNS is not available)." default "20.47.97.44" config COAP_SERVER_PORT - int "CoAP server port number (DTLS)" + int "CoAP server port number (DTLS)." default "5684" config DTLS_PSK_IDENTITY - string "CoAP/DTLS PSK identity" + string "CoAP/DTLS PSK identity." default "cali.${imei}" + help + "${imei}" is replaced by the modem's IMEI. + This only work with Californium's PlugTestServer, + which implements "wildcard" identities to + make it easier to connect. + Don't use this on production or other security + relevant use-cases. config DTLS_PSK_SECRET - string "CoAP/DTLS PSK secret" + string "CoAP/DTLS PSK secret." default ".fornium" + help + This only work with Californium's PlugTestServer, + and the "cali.*" wildcard identity. + Don't use this on production or other security + relevant use-cases. config COAP_SEND_INTERVAL int "CoAP send interval in seconds. 0 disable" default 0 +config COAP_WAKEUP_SEND_INTERVAL + int "Wakeup CoAP send interval in seconds. 0 disable." + default 3500 + depends on UDP_PSM_ENABLE + help + Using PSM (Power Sleeping Mode) the modem frequently wakesup to refresh + the network registration. This interval is used to exchange messages + piggybacked on such an wakeup. The interval doesn't trigger such a wakeup, + so it's usully chosen a little smaller than the PSM interval. + Ignored, if COAP_SEND_INTERVAL is enabled. + config COAP_RESOURCE string "CoAP resource - defaults to Californium's echo resource" default "echo" @@ -49,6 +72,9 @@ config COAP_QUERY_KEEP_ENABLE bool "Enable CoAP query - keep" default y +endmenu + +menu "Modem Settings" config UDP_PSM_ENABLE bool "Enable LTE Power Saving Mode" default y @@ -58,7 +84,7 @@ config UDP_RAI_ENABLE default y config MODEM_SAVE_CONFIG_THRESHOLD - int "Modem save configuration threshold in seconds. Default 60s" + int "Modem save configuration threshold in seconds. 0s, don't save, 1s always save. Default 60s" default 60 help If the initial network connect takes more than the threshold, diff --git a/prj.conf b/prj.conf index e33c6d9..dcbaae4 100644 --- a/prj.conf +++ b/prj.conf @@ -26,7 +26,6 @@ CONFIG_BOOTLOADER_MCUBOOT=y CONFIG_MAIN_STACK_SIZE=6000 CONFIG_HEAP_MEM_POOL_SIZE=16384 CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=4096 -CONFIG_HW_STACK_PROTECTION=y CONFIG_REBOOT=y @@ -35,7 +34,7 @@ CONFIG_REBOOT=y # Logging CONFIG_LOG=y -CONFIG_LOG2_MODE_DEFERRED=y +CONFIG_LOG_MODE_DEFERRED=y CONFIG_LOG_BACKEND_FORMAT_TIMESTAMP=y # Network @@ -76,8 +75,10 @@ CONFIG_LTE_PSM_REQ_RPTAU="00100001" # 000xxxxx : 10 minutes # CONFIG_LTE_PSM_REQ_RPTAU="00000001" -# 000xxxxx : 2 seconds +# 000xxxxx : 2 seconds CONFIG_LTE_PSM_REQ_RAT="00000100" +# 00000000 : immediately +# CONFIG_LTE_PSM_REQ_RAT="00000000" ## RAI CONFIG_UDP_RAI_ENABLE=y @@ -85,12 +86,12 @@ CONFIG_LTE_RAI_REQ_VALUE="3" CONFIG_LTE_LOCK_BANDS=n -#CONFIG_LTE_LOCK_PLMN=y +# CONFIG_LTE_LOCK_PLMN=y # Germany: # - Telekom: 26201 # - Vodafone: 26202 # - Telefonica: 26203 -#CONFIG_LTE_LOCK_PLMN_STRING="26201" +# CONFIG_LTE_LOCK_PLMN_STRING="26203" ## CoAP CONFIG_COAP=y diff --git a/src/coap_client.c b/src/coap_client.c index 6025cc3..e41a48a 100644 --- a/src/coap_client.c +++ b/src/coap_client.c @@ -139,6 +139,7 @@ int coap_client_prepare_post(void) uint8_t *token = (uint8_t *)&coap_current_token; struct coap_packet request; struct lte_lc_psm_cfg psm; + uint32_t psm_delays; #ifdef CONFIG_COAP_QUERY_DELAY_ENABLE static int query_delay = 0; @@ -223,8 +224,8 @@ int coap_client_prepare_post(void) index += snprintf(buf + index, sizeof(buf) - index, "\n"); start = index; - if (modem_get_psm_status(&psm) == 0) { - index += snprintf(buf + index, sizeof(buf) - index, "PSM: %d/%d [s]", psm.tau,psm.active_time); + if (modem_get_psm_status(&psm, &psm_delays) == 0) { + index += snprintf(buf + index, sizeof(buf) - index, "PSM: TAU %d [s], Act %d [s], Delays %d", psm.tau, psm.active_time, psm_delays); } err = modem_get_release_time(); if (err > 0) { @@ -234,6 +235,10 @@ int coap_client_prepare_post(void) index += snprintf(buf + index, sizeof(buf) - index, "Released: %d ms", err); } dtls_info("%s", buf + start); + start = index + 1; + index += snprintf(buf + index, sizeof(buf) - index, "\nStat: "); + index += modem_read_statistic(buf + index, sizeof(buf) - index); + dtls_info("%s", buf + start); #ifdef CONFIG_LOCATION_ENABLE err = 1; diff --git a/src/coap_client.h b/src/coap_client.h index 403e54f..3fc31d5 100644 --- a/src/coap_client.h +++ b/src/coap_client.h @@ -16,7 +16,7 @@ #include "dtls.h" -#define CLIENT_VERSION "v0.3" +#define CLIENT_VERSION "v0.4" #define COAP_MAX_RETRANSMISSION 3 #define BAT_LEVEL_SLOTS 10 diff --git a/src/dtls_client.c b/src/dtls_client.c index d542b9b..2e8d318 100644 --- a/src/dtls_client.c +++ b/src/dtls_client.c @@ -22,7 +22,6 @@ #include "coap_client.h" #include "dtls.h" -#include "dtls_client.h" #include "dtls_credentials.h" #include "dtls_debug.h" #include "global.h" @@ -70,19 +69,20 @@ static int timeout = 0; /* the wakeup send interval is only effecitve on PSM wakeup */ /* the granularity of this time is therefore the PSM time */ -#define NETWORK_WAKEUP_SEND_INTERVAL_S (3600 * 1 - 100) /* approx. 1h */ + +//#define NETWORK_WAKEUP_SEND_INTERVAL_S (3600 * 1 - 100) /* approx. 1h */ #if (defined CONFIG_LTE_MODE_PREFERENCE_NBIOT_PLMN_PRIO || defined CONFIG_LTE_MODE_PREFERENCE_LTE_M_PLMN_PRIO) #define NETWORK_TIMEOUT_S 360 #else -#define NETWORK_TIMEOUT_S 360 +#define NETWORK_TIMEOUT_S 240 #endif #define RTT_SLOTS 9 #define RTT_INTERVAL 2000 static unsigned int rtts[RTT_SLOTS + 2] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20}; -K_SEM_DEFINE(dtls_trigger_msg, 0, 1); +K_SEM_DEFINE(dtls_trigger_msg, 1, 1); K_SEM_DEFINE(dtls_trigger_search, 0, 1); static void reboot() @@ -141,7 +141,7 @@ static void reopen_socket(struct dtls_context_t *ctx) { int err; dtls_warn("> reconnect modem"); - modem_set_power_modes(0); + modem_set_rai(0); err = modem_start(K_SECONDS(NETWORK_TIMEOUT_S)); if (err) { reconnect(); @@ -153,9 +153,47 @@ static void reopen_socket(struct dtls_context_t *ctx) dtls_warn("> reopen UDP socket failed, %d, errno %d (%s), reboot", *fd, errno, strerror(errno)); reboot(); } - modem_set_power_modes(1); + modem_set_rai(1); +} +static void dtls_trigger(void) +{ + if (request_state == NONE) { + k_sem_give(&dtls_trigger_msg); + } +} + +static void dtls_manual_trigger(void) +{ + ui_led_op(LED_COLOR_RED, LED_CLEAR); + k_sem_give(&dtls_trigger_search); + dtls_trigger(); +} + +#if CONFIG_COAP_SEND_INTERVAL > 0 +static void dtls_timer_trigger_fn(struct k_work *work) +{ + dtls_trigger(); } +static K_WORK_DELAYABLE_DEFINE(dtls_timer_trigger_work, dtls_timer_trigger_fn); + +#elif CONFIG_COAP_WAKEUP_SEND_INTERVAL > 0 +static void dtls_wakeup_trigger(void) +{ + static unsigned long wakeup_next_sent = 0; + unsigned long now = (unsigned long)k_uptime_get(); + + if (request_state == NONE) { + if (wakeup_next_sent <= now) { + dtls_trigger(); + } else { + return; + } + } + wakeup_next_sent = now + ((CONFIG_COAP_WAKEUP_SEND_INTERVAL)*MSEC_PER_SEC); +} +#endif + static void dtls_coap_success(void) { long time1 = connected_time - connect_time; @@ -207,6 +245,9 @@ static void dtls_coap_success(void) dtls_info("vbat: %u, %u, %u, %u, %u", bat_level[0], bat_level[1], bat_level[2], bat_level[3], bat_level[4]); dtls_info(" %u, %u, %u, %u, %u", bat_level[5], bat_level[6], bat_level[7], bat_level[8], bat_level[9]); } +#if CONFIG_COAP_SEND_INTERVAL > 0 + k_work_schedule(&dtls_timer_trigger_work, K_SECONDS(CONFIG_COAP_SEND_INTERVAL)); +#endif } static void dtls_coap_failure(void) @@ -227,6 +268,9 @@ static void dtls_coap_failure(void) ui_led_op(LED_COLOR_BLUE, LED_CLEAR); dtls_info("%u/%ldms/%ldms: failure", lte_connections, time1, time2); transmissions[COAP_MAX_RETRANSMISSION + 1]++; +#if CONFIG_COAP_SEND_INTERVAL > 0 + k_work_schedule(&dtls_timer_trigger_work, K_SECONDS(CONFIG_COAP_SEND_INTERVAL)); +#endif } static int @@ -359,14 +403,14 @@ dtls_handle_event(struct dtls_context_t *ctx, session_t *session, request_state = NONE; ui_led_op(LED_COLOR_RED, LED_CLEAR); ui_led_op(LED_COLOR_GREEN, LED_CLEAR); - modem_set_power_modes(1); + modem_set_rai(1); } else if (DTLS_EVENT_CONNECT == code) { dtls_info("dtls connect ..."); dtls_connected = 0; ui_led_op(LED_COLOR_BLUE, LED_CLEAR); ui_led_op(LED_COLOR_RED, LED_SET); ui_led_op(LED_COLOR_GREEN, LED_SET); - modem_set_power_modes(0); + modem_set_rai(0); } return 0; } @@ -415,7 +459,7 @@ static dtls_handler_t cb = { .event = dtls_handle_event, }; -void dtls_lte_connected(enum dtls_lte_connect_type type, int connected) +static void dtls_lte_connected(enum dtls_lte_connect_type type, bool connected) { if (type == LTE_CONNECT_NETWORK) { network_connected = connected; @@ -507,44 +551,6 @@ static int dtls_init_destination(session_t *destination) return 0; } -static void dtls_trigger(void) -{ - if (request_state == NONE) { - k_sem_give(&dtls_trigger_msg); - } -} - -static void dtls_manual_trigger(void) -{ - ui_led_op(LED_COLOR_RED, LED_CLEAR); - k_sem_give(&dtls_trigger_search); - dtls_trigger(); -} - -static void dtls_wakeup_trigger(void) -{ - static unsigned long wakeup_next_sent = 0; - unsigned long now = (unsigned long)k_uptime_get(); - - if (request_state == NONE) { - if (wakeup_next_sent <= now) { - dtls_trigger(); - } else { - return; - } - } - wakeup_next_sent = now + ((NETWORK_WAKEUP_SEND_INTERVAL_S)*MSEC_PER_SEC); -} - -#if CONFIG_COAP_SEND_INTERVAL > 0 -static void dtls_timer_trigger_fn(struct k_work *work) -{ - dtls_trigger(); -} - -static K_WORK_DELAYABLE_DEFINE(dtls_timer_trigger_work, dtls_timer_trigger_fn); -#endif - #ifdef CONFIG_ADXL362_MOTION_DETECTION static void accelerometer_handler(const struct accelerometer_evt *const evt) { @@ -584,7 +590,7 @@ int dtls_loop(void) reboot(); } - modem_set_power_modes(0); + modem_set_rai(0); imei_len = modem_at_cmd("AT+CGSN", imei, sizeof(imei), NULL); dtls_credentials_init_psk(0 < imei_len ? imei : NULL); dtls_credentials_init_handler(&cb); @@ -748,7 +754,11 @@ void main(void) ui_init(dtls_manual_trigger); - modem_init(dtls_wakeup_trigger); +#if CONFIG_COAP_WAKEUP_SEND_INTERVAL > 0 && CONFIG_COAP_SEND_INTERVAL == 0 + modem_init(dtls_wakeup_trigger, dtls_lte_connected); +#else + modem_init(NULL, dtls_lte_connected); +#endif #ifdef CONFIG_LOCATION_ENABLE #ifdef CONFIG_LOCATION_ENABLE_TRIGGER_MESSAGE diff --git a/src/dtls_client.h b/src/dtls_client.h deleted file mode 100644 index 5703dfa..0000000 --- a/src/dtls_client.h +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright (c) 2022 Achim Kraus CloudCoap.net - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0 - * - * SPDX-License-Identifier: EPL-2.0 - */ - -#ifndef DTLS_CLIENT_H -#define DTLS_CLIENT_H - -enum dtls_lte_connect_type { - LTE_CONNECT_NETWORK, - LTE_CONNECT_TRANSMISSION -}; - -void dtls_lte_connected(enum dtls_lte_connect_type type, int connected); - -int dtls_loop(void); - -#endif /* DTLS_CLIENT_ */ diff --git a/src/modem.c b/src/modem.c index 57ba706..95490d3 100644 --- a/src/modem.c +++ b/src/modem.c @@ -14,14 +14,12 @@ #include #include #include -#include #include #include #include #include #include -#include "dtls_client.h" #include "modem.h" #include "ui.h" @@ -34,9 +32,9 @@ static K_CONDVAR_DEFINE(lte_condvar); static K_SEM_DEFINE(ptau_update, 0, 1); -static wakeup_callback_handler_t wakeup_handler = NULL; +static wakeup_callback_handler_t s_wakeup_handler = NULL; +static connect_callback_handler_t s_connect_handler = NULL; static bool initialized = 0; -static bool start_connect = 0; static volatile int lte_connected_state = 0; @@ -44,9 +42,10 @@ static const char *volatile network_mode = "init"; static struct lte_lc_edrx_cfg edrx_status = {LTE_LC_LTE_MODE_NONE, 0.0, 0.0}; static struct lte_lc_psm_cfg psm_status = {0, 0}; +static uint32_t psm_delays = 0; static bool plmn_lock = false; static char provider[12] = "00,00000(*)"; -static unsigned long transmission_time = 0; +static int64_t transmission_time = 0; static volatile int rai_time = -1; @@ -87,6 +86,13 @@ static void lte_set_psm_status(const struct lte_lc_psm_cfg *psm) k_mutex_unlock(<e_mutex); } +static void lte_inc_psm_delays(void) +{ + k_mutex_lock(<e_mutex, K_FOREVER); + ++psm_delays; + k_mutex_unlock(<e_mutex); +} + static int64_t get_transmission_time(void) { int64_t time; @@ -96,13 +102,13 @@ static int64_t get_transmission_time(void) return time; } -static const char *modem_next_string(const char *value) +static const char *modem_next_char(const char *value, char sep) { if (value) { - while (*value && *value != '"') { + while (*value && *value != sep) { ++value; } - if (*value == '"') { + if (*value == sep) { ++value; if (*value) { return value; @@ -112,6 +118,28 @@ static const char *modem_next_string(const char *value) return NULL; } +static const char *modem_next_chars(const char *value, char sep, int count) +{ + for (int index = 0; index < count; ++index) { + value = modem_next_char(value, sep); + } + return value; +} + +static int modem_strncpy(char *buf, const char *value, char end, int size) +{ + int index; + for (index = 0; index < size; ++index) { + char cur = *value; + if (!cur || cur == end) { + break; + } + buf[index] = cur; + value++; + } + return index; +} + static void modem_read_operator_info() { int index; @@ -126,23 +154,15 @@ static void modem_read_operator_info() memset(temp, 0, sizeof(temp)); - for (index = 0; index < 3; ++index) { - if (*cur != ',') { - *t++ = *cur++; - } - } + index = modem_strncpy(t, cur, ',', 3); + t += index; + cur += index; if (*cur == ',') { *t++ = *cur++; // skip 2 parameter "...", find start of 3th parameter. - for (index = 0; index < 5; ++index) { - cur = modem_next_string(cur); - } + cur = modem_next_chars(cur, '"', 5); if (cur) { - for (index = 0; index < 5; ++index) { - if (*cur != '"') { - *t++ = *cur++; - } - } + t += modem_strncpy(t, cur, '"', 5); } } if (plmn_lock) { @@ -159,7 +179,7 @@ static void modem_read_operator_info() static void lte_registration(enum lte_lc_nw_reg_status reg_status) { const char *description = "unknown"; - int connected = 0; + bool connected = false; switch (reg_status) { case LTE_LC_NW_REG_NOT_REGISTERED: @@ -167,7 +187,7 @@ static void lte_registration(enum lte_lc_nw_reg_status reg_status) break; case LTE_LC_NW_REG_REGISTERED_HOME: description = "Connected - home network"; - connected = 1; + connected = true; break; case LTE_LC_NW_REG_SEARCHING: description = "Searching ..."; @@ -179,11 +199,11 @@ static void lte_registration(enum lte_lc_nw_reg_status reg_status) break; case LTE_LC_NW_REG_REGISTERED_ROAMING: description = "Connected - roaming network"; - connected = 1; + connected = true; break; case LTE_LC_NW_REG_REGISTERED_EMERGENCY: description = "Connected - emergency network"; - connected = 1; + connected = true; break; case LTE_LC_NW_REG_UICC_FAIL: description = "Not Connected - UICC fail"; @@ -191,14 +211,18 @@ static void lte_registration(enum lte_lc_nw_reg_status reg_status) } lte_connection_set(connected); - dtls_lte_connected(LTE_CONNECT_NETWORK, connected); - + if (s_connect_handler) { + s_connect_handler(LTE_CONNECT_NETWORK, connected); + } LOG_INF("Network registration status: %s", description); } static void lte_handler(const struct lte_lc_evt *const evt) { static int64_t connect_time = 0; + static int64_t idle_time = 0; + static int active_time = -1; + switch (evt->type) { case LTE_LC_EVT_NW_REG_STATUS: lte_registration(evt->nw_reg_status); @@ -216,7 +240,8 @@ static void lte_handler(const struct lte_lc_evt *const evt) case LTE_LC_EVT_PSM_UPDATE: LOG_INF("PSM parameter update: TAU: %d s, Active time: %d s", evt->psm_cfg.tau, evt->psm_cfg.active_time); - if (evt->psm_cfg.active_time > 0) { + active_time = evt->psm_cfg.active_time; + if (evt->psm_cfg.active_time >= 0) { lte_set_psm_status(&evt->psm_cfg); k_sem_give(&ptau_update); } @@ -242,17 +267,21 @@ static void lte_handler(const struct lte_lc_evt *const evt) if (evt->rrc_mode == LTE_LC_RRC_MODE_CONNECTED) { connect_time = now; LOG_INF("RRC mode: Connected"); - dtls_lte_connected(LTE_CONNECT_TRANSMISSION, 1); + if (s_connect_handler) { + s_connect_handler(LTE_CONNECT_TRANSMISSION, true); + } } else { int64_t time = get_transmission_time(); + idle_time = now; if ((time - connect_time) > 0) { rai_time = (int)(now - time); LOG_INF("RRC mode: Idle after %lld ms (%d ms inactivity)", now - connect_time, rai_time); - dtls_lte_connected(LTE_CONNECT_TRANSMISSION, 0); } else { rai_time = -1; LOG_INF("RRC mode: Idle after %lld ms", now - connect_time); - dtls_lte_connected(LTE_CONNECT_TRANSMISSION, 0); + } + if (s_connect_handler) { + s_connect_handler(LTE_CONNECT_TRANSMISSION, false); } } break; @@ -264,12 +293,21 @@ static void lte_handler(const struct lte_lc_evt *const evt) LOG_INF("LTE cell changed: Cell ID: %d, Tracking area: %d", evt->cell.id, evt->cell.tac); break; case LTE_LC_EVT_MODEM_SLEEP_ENTER: - LOG_INF("LTE modem sleeps"); + if (idle_time) { + int64_t time = (k_uptime_get() - idle_time); + bool delayed = active_time >= 0 && ((time / MSEC_PER_SEC) > (active_time + 5)); + if (delayed) { + lte_inc_psm_delays(); + } + LOG_INF("LTE modem sleeps after %lld ms idle%s", time, delayed ? ", delaye" : ""); + } else { + LOG_INF("LTE modem sleeps"); + } break; case LTE_LC_EVT_MODEM_SLEEP_EXIT: LOG_INF("LTE modem wakes up"); - if (wakeup_handler) { - wakeup_handler(); + if (s_wakeup_handler) { + s_wakeup_handler(); } break; case LTE_LC_EVT_MODEM_EVENT: @@ -307,19 +345,22 @@ static int modem_connect(void) if (IS_ENABLED(CONFIG_LTE_AUTO_INIT_AND_CONNECT)) { /* Do nothing, modem is already configured and LTE connected. */ - } else if (!start_connect) { + } else { + lte_lc_modem_events_enable(); err = lte_lc_connect_async(lte_handler); if (err) { - LOG_WRN("Connecting to LTE network failed, error: %d", - err); - } else { - start_connect = true; + if (err == -EINPROGRESS) { + LOG_INF("Connecting to LTE network in progress"); + err = 0; + } else { + LOG_WRN("Connecting to LTE network failed, error: %d", err); + } } } return err; } -int modem_init(wakeup_callback_handler_t handler) +int modem_init(wakeup_callback_handler_t wakeup_handler, connect_callback_handler_t connect_handler) { int err = 0; @@ -327,6 +368,7 @@ int modem_init(wakeup_callback_handler_t handler) /* Do nothing, modem is already configured and LTE connected. */ } else if (!initialized) { char buf[32]; + nrf_modem_lib_init(NORMAL_MODE); err = modem_at_cmd("AT%%HWVERSION", buf, sizeof(buf), "%HWVERSION: "); if (err > 0) { @@ -339,7 +381,7 @@ int modem_init(wakeup_callback_handler_t handler) #if 0 err = modem_at_cmd("AT%%XFACTORYRESET=0", buf, sizeof(buf), NULL); LOG_INF("Factory reset: %s", buf); - k_sleep(K_MINUTES(5)); + k_sleep(K_SECONDS(10)); #endif #if 0 err = modem_at_cmd("AT%%REL14FEAT=0,1,0,0,0", buf, sizeof(buf), NULL); @@ -347,6 +389,11 @@ int modem_init(wakeup_callback_handler_t handler) LOG_INF("rel14feat: %s", buf); } #endif + int err = modem_at_cmd("AT%%XCONNSTAT=1", buf, sizeof(buf), NULL); + if (err > 0) { + LOG_INF("stat: %s", buf); + } + #ifdef CONFIG_UDP_PSM_ENABLE err = lte_lc_psm_req(true); if (err) { @@ -374,21 +421,50 @@ int modem_init(wakeup_callback_handler_t handler) return err; } initialized = true; - wakeup_handler = handler; + + s_wakeup_handler = wakeup_handler; + s_connect_handler = connect_handler; LOG_INF("modem initialized"); } - + if (initialized) { + if (wakeup_handler) { + s_wakeup_handler = wakeup_handler; + } + if (connect_handler) { + s_connect_handler = connect_handler; + } + } return err; } -int modem_start(const k_timeout_t timeout) +static int modem_connection_wait(const k_timeout_t timeout) { int err = 0; k_timeout_t time = K_MSEC(0); k_timeout_t interval = K_MSEC(1500); -#if CONFIG_MODEM_SAVE_CONFIG_THRESHOLD > 0 - k_timeout_t save = K_SECONDS(CONFIG_MODEM_SAVE_CONFIG_THRESHOLD); -#endif + int led_on = 1; + while (!lte_connection_wait(interval)) { + led_on = !led_on; + if (led_on) { + ui_led_op(LED_COLOR_BLUE, LED_SET); + ui_led_op(LED_COLOR_RED, LED_SET); + } else { + ui_led_op(LED_COLOR_BLUE, LED_CLEAR); + ui_led_op(LED_COLOR_RED, LED_CLEAR); + } + time.ticks += interval.ticks; + if ((time.ticks - timeout.ticks) > 0) { + err = 1; + break; + } + } + return err; +} + +int modem_start(const k_timeout_t timeout) +{ + int err = 0; + int64_t time; #ifdef CONFIG_LTE_MODE_PREFERENCE_LTE_M LOG_INF("LTE-M preference."); @@ -411,36 +487,25 @@ int modem_start(const k_timeout_t timeout) ui_led_op(LED_COLOR_BLUE, LED_SET); ui_led_op(LED_COLOR_RED, LED_SET); - /* Initialize the modem before calling configure_low_power(). This is - * because the enabling of RAI is dependent on the - * configured network mode which is set during modem initialization. - */ + err = modem_connect(); if (!err) { - err = modem_connect(); - } - if (!err) { - int led_on = 1; - while (!lte_connection_wait(interval)) { - led_on = !led_on; - if (led_on) { - ui_led_op(LED_COLOR_BLUE, LED_SET); - ui_led_op(LED_COLOR_RED, LED_SET); - } else { - ui_led_op(LED_COLOR_BLUE, LED_CLEAR); - ui_led_op(LED_COLOR_RED, LED_CLEAR); - } - time.ticks += interval.ticks; - if ((time.ticks - timeout.ticks) > 0) { - err = 1; - break; - } + time = k_uptime_get(); + err = modem_connection_wait(timeout); + time = k_uptime_get() - time; + if (!err) { + LOG_INF("LTE connected in %ld [ms]", (long)time); } #if CONFIG_MODEM_SAVE_CONFIG_THRESHOLD > 0 - if ((time.ticks - save.ticks) > 0) { +#if CONFIG_MODEM_SAVE_CONFIG_THRESHOLD == 1 + if (1) { +#else + if (time > CONFIG_MODEM_SAVE_CONFIG_THRESHOLD * MSEC_PER_SEC) { +#endif LOG_INF("Modem saving ..."); - lte_lc_offline(); + lte_lc_power_off(); lte_lc_normal(); LOG_INF("Modem saved."); + err = modem_connection_wait(timeout); } else { LOG_INF("Modem not saved."); } @@ -464,12 +529,19 @@ int modem_get_edrx_status(struct lte_lc_edrx_cfg *edrx) return (edrx->mode != LTE_LC_LTE_MODE_NONE) ? 0 : -ENODATA; } -int modem_get_psm_status(struct lte_lc_psm_cfg *psm) +int modem_get_psm_status(struct lte_lc_psm_cfg *psm, uint32_t *delays) { + int tau; k_mutex_lock(<e_mutex, K_FOREVER); - *psm = psm_status; + tau = psm_status.tau; + if (psm) { + *psm = psm_status; + } + if (delays) { + *delays = psm_delays; + } k_mutex_unlock(<e_mutex); - return (psm->tau > 0) ? 0 : -ENODATA; + return (tau >= 0) ? 0 : -ENODATA; } int modem_get_release_time(void) @@ -499,6 +571,22 @@ int modem_read_provider(char *buf, size_t len) return modem_get_provider(buf, len); } +int modem_read_statistic(char *data, size_t len) +{ + int err; + char buf[92]; + + memset(data, 0, len); + err = modem_at_cmd("AT%%XCONNSTAT?", buf, sizeof(buf), "%XCONNSTAT: "); + if (err > 0) { + const char *cur = modem_next_chars(buf, ',', 2); + if (cur) { + strncpy(data, cur, len); + } + } + return strlen(data); +} + int modem_at_cmd(const char *cmd, char *buf, size_t max_len, const char *skip) { int err; @@ -517,22 +605,12 @@ int modem_at_cmd(const char *cmd, char *buf, size_t max_len, const char *skip) return strlen(buf); } -int modem_set_power_modes(int enable) +int modem_set_rai(int enable) { int err = 0; +#ifdef CONFIG_UDP_RAI_ENABLE if (enable) { -#if defined(CONFIG_UDP_PSM_ENABLE) - /** Power Saving Mode */ - err = lte_lc_psm_req(true); - if (err) { - LOG_WRN("lte_lc_psm_req, error: %d", err); - } else { - k_sem_take(&ptau_update, K_SECONDS(10)); - LOG_INF("lte_lc_psm_req, enabled. TAU: %d s, Act: %d s", psm_status.tau, psm_status.active_time); - } -#endif -#if defined(CONFIG_UDP_RAI_ENABLE) /** Release Assistance Indication */ err = lte_lc_rai_req(true); if (err) { @@ -540,14 +618,7 @@ int modem_set_power_modes(int enable) } else { LOG_INF("lte_lc_rai_req, enabled."); } -#endif } else { - err = lte_lc_psm_req(false); - if (err) { - LOG_WRN("lte_lc_psm_req disable, error: %d", err); - } else { - LOG_INF("lte_lc_psm_req, disabled."); - } err = lte_lc_rai_req(false); if (err) { LOG_WRN("lte_lc_rai_req disable, error: %d", err); @@ -555,6 +626,7 @@ int modem_set_power_modes(int enable) LOG_INF("lte_lc_rai_req, disabled."); } } +#endif return err; } @@ -575,14 +647,16 @@ int modem_power_off(void) #else -int modem_init(wakeup_callback_handler_t handler) +int modem_init(wakeup_callback_handler_t wakeup_handler, connect_callback_handler_t connect_handler) { + (void)wakeup_handler; + (void)connect_handler; return 0; } -int modem_start(int init) +int modem_start(const k_timeout_t timeout) { - (void)init; + (void)timeout; return 0; } @@ -597,9 +671,10 @@ int modem_get_edrx_status(struct lte_lc_edrx_cfg *edrx) return -ENODATA; } -int modem_get_psm_status(struct lte_lc_psm_cfg *psm) +int modem_get_psm_status(struct lte_lc_psm_cfg *psm, uint32_t *delays) { (void)psm; + (void)delays; return -ENODATA; } @@ -621,7 +696,7 @@ int modem_at_cmd(const char *cmd, char *buf, size_t max_len, const char *skip) return 0; } -int modem_set_power_modes(int enable) +int modem_set_rai(int enable) { (void)enable; return 0; diff --git a/src/modem.h b/src/modem.h index 0014981..8941e3a 100644 --- a/src/modem.h +++ b/src/modem.h @@ -15,13 +15,20 @@ #define MODEM_H #include +#include #include #include +enum dtls_lte_connect_type { + LTE_CONNECT_NETWORK, + LTE_CONNECT_TRANSMISSION +}; + typedef void (*wakeup_callback_handler_t)(void); +typedef void (*connect_callback_handler_t)(enum dtls_lte_connect_type type, bool connected); -int modem_init(wakeup_callback_handler_t handler); +int modem_init(wakeup_callback_handler_t wakeup_handler, connect_callback_handler_t connect_handler); int modem_start(const k_timeout_t timeout); @@ -29,7 +36,7 @@ const char* modem_get_network_mode(void); int modem_get_edrx_status(struct lte_lc_edrx_cfg *edrx); -int modem_get_psm_status(struct lte_lc_psm_cfg *psm); +int modem_get_psm_status(struct lte_lc_psm_cfg *psm, uint32_t* delays); int modem_get_provider(char* buf, size_t len); @@ -39,9 +46,11 @@ void modem_set_transmission_time(void); int modem_read_provider(char* buf, size_t len); +int modem_read_statistic(char *buf, size_t len); + int modem_at_cmd(const char* cmd, char* buf, size_t max_len, const char *skip); -int modem_set_power_modes(int enable); +int modem_set_rai(int enable); int modem_set_offline(void); diff --git a/src/power_manager.c b/src/power_manager.c index 9f6b989..51b523a 100644 --- a/src/power_manager.c +++ b/src/power_manager.c @@ -128,7 +128,7 @@ int power_manager_status(uint8_t *level, uint16_t *voltage, power_manager_status int power_manager_init(void) { - modem_init(NULL); + modem_init(NULL, NULL); return 0; }