Skip to content

Commit 7e2eb13

Browse files
committed
Add LTE metrics
1 parent 7e19044 commit 7e2eb13

File tree

21 files changed

+711
-164
lines changed

21 files changed

+711
-164
lines changed

applications/asset_tracker_v2/configuration/memfault/memfault_metrics_heartbeat_config.def

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,6 @@
22
* Please refer to https://docs.memfault.com/docs/embedded/metrics-api for more details.
33
*/
44

5-
MEMFAULT_METRICS_KEY_DEFINE(GnssTimeToFix, kMemfaultMetricType_Unsigned)
6-
MEMFAULT_METRICS_KEY_DEFINE(GnssSatellitesTracked, kMemfaultMetricType_Unsigned)
7-
MEMFAULT_METRICS_KEY_DEFINE(LocationTimeoutSearchTime, kMemfaultMetricType_Unsigned)
5+
MEMFAULT_METRICS_KEY_DEFINE(gnss_time_to_fix_ms, kMemfaultMetricType_Unsigned)
6+
MEMFAULT_METRICS_KEY_DEFINE(gnss_satellites_tracked_count, kMemfaultMetricType_Unsigned)
7+
MEMFAULT_METRICS_KEY_DEFINE(location_timeout_search_time_ms, kMemfaultMetricType_Unsigned)

applications/asset_tracker_v2/doc/debug_module.rst

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,9 @@ Memfault
2525
The debug module uses `Memfault SDK`_ to track |NCS| specific metrics such as LTE and stack metrics.
2626
In addition, the following types of custom Memfault metrics are defined and tracked when compiling in the debug module:
2727

28-
* ``GnssTimeToFix`` - Time duration between the start of a GNSS search and obtaining a fix.
29-
* ``GnssSatellitesTracked`` - Number of satellites tracked during a GNSS search window.
30-
* ``LocationTimeoutSearchTime`` - Time duration between the start of a location search and a search timeout.
28+
* ``gnss_time_to_fix_ms`` - Time duration between the start of a GNSS search and obtaining a fix.
29+
* ``gnss_satellites_tracked_count`` - Number of satellites tracked during a GNSS search window.
30+
* ``location_timeout_search_time_ms`` - Time duration between the start of a location search and a search timeout.
3131

3232
The debug module also implements `Memfault SDK`_ software watchdog, which is designed to trigger an assert before an actual watchdog timeout.
3333
This enables the application to be able to collect coredump data before a reboot occurs.

applications/asset_tracker_v2/src/modules/debug_module.c

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -264,30 +264,26 @@ static void add_location_metrics(uint8_t satellites, uint32_t search_time,
264264

265265
switch (event) {
266266
case LOCATION_MODULE_EVT_GNSS_DATA_READY:
267-
err = memfault_metrics_heartbeat_set_unsigned(
268-
MEMFAULT_METRICS_KEY(GnssTimeToFix),
269-
search_time);
267+
err = MEMFAULT_METRIC_SET_UNSIGNED(gnss_time_to_fix_ms, search_time);
270268
if (err) {
271-
LOG_ERR("Failed updating GnssTimeToFix metric, error: %d", err);
269+
LOG_ERR("Failed updating gnss_time_to_fix_ms metric, error: %d", err);
272270
}
273271
break;
274272
case LOCATION_MODULE_EVT_TIMEOUT:
275-
err = memfault_metrics_heartbeat_set_unsigned(
276-
MEMFAULT_METRICS_KEY(LocationTimeoutSearchTime),
277-
search_time);
273+
err = MEMFAULT_METRIC_SET_UNSIGNED(location_timeout_search_time_ms, search_time);
278274
if (err) {
279-
LOG_ERR("Failed updating LocationTimeoutSearchTime metric, error: %d", err);
275+
LOG_ERR("Failed updating location_timeout_search_time_ms metric, error: %d",
276+
err);
280277
}
281278
break;
282279
default:
283280
LOG_ERR("Unknown location module event.");
284281
return;
285282
}
286283

287-
err = memfault_metrics_heartbeat_set_unsigned(MEMFAULT_METRICS_KEY(GnssSatellitesTracked),
288-
satellites);
284+
err = MEMFAULT_METRIC_SET_UNSIGNED(gnss_satellites_tracked_count, satellites);
289285
if (err) {
290-
LOG_ERR("Failed updating GnssSatellitesTracked metric, error: %d", err);
286+
LOG_ERR("Failed updating gnss_satellites_tracked_count metric, error: %d", err);
291287
}
292288

293289
memfault_metrics_heartbeat_debug_trigger();

applications/asset_tracker_v2/tests/debug_module/src/debug_module_test.c

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -114,11 +114,9 @@ void test_memfault_trigger_metric_sampling_on_gnss_fix(void)
114114
setup_debug_module_in_init_state();
115115

116116
__cmock_memfault_metrics_heartbeat_set_unsigned_ExpectAndReturn(
117-
MEMFAULT_METRICS_KEY(GnssTimeToFix),
118-
60000,
119-
0);
117+
MEMFAULT_METRICS_KEY(gnss_time_to_fix_ms), 60000, 0);
120118
__cmock_memfault_metrics_heartbeat_set_unsigned_ExpectAndReturn(
121-
MEMFAULT_METRICS_KEY(GnssSatellitesTracked),
119+
MEMFAULT_METRICS_KEY(gnss_satellites_tracked_count),
122120
4,
123121
0);
124122
__cmock_memfault_metrics_heartbeat_debug_trigger_Expect();
@@ -144,11 +142,11 @@ void test_memfault_trigger_metric_sampling_on_location_timeout(void)
144142

145143
/* Update this function to expect the search time and number of satellites. */
146144
__cmock_memfault_metrics_heartbeat_set_unsigned_ExpectAndReturn(
147-
MEMFAULT_METRICS_KEY(LocationTimeoutSearchTime),
145+
MEMFAULT_METRICS_KEY(location_timeout_search_time_ms),
148146
30000,
149147
0);
150148
__cmock_memfault_metrics_heartbeat_set_unsigned_ExpectAndReturn(
151-
MEMFAULT_METRICS_KEY(GnssSatellitesTracked),
149+
MEMFAULT_METRICS_KEY(gnss_satellites_tracked_count),
152150
2,
153151
0);
154152
__cmock_memfault_metrics_heartbeat_debug_trigger_Ignore();

include/modem/modem_info.h

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,20 @@ extern "C" {
4343
/** Modem firmware version string can be up to 40 characters long. */
4444
#define MODEM_INFO_FWVER_SIZE 41
4545

46+
/** Band unavailable value. */
47+
#define BAND_UNAVAILABLE 0
48+
49+
/** Short operator size can be up to 64 characters long.
50+
* Matches value in nrf/samples/cellular/modem_shell/src/link/link_api.h.
51+
*/
52+
#define MODEM_INFO_SHORT_OP_NAME_SIZE 65
53+
54+
/** SNR unavailable value. */
55+
#define SNR_UNAVAILABLE 127
56+
57+
/** SNR offset value. */
58+
#define SNR_OFFSET_VAL 24
59+
4660
/** Modem returns RSRP and RSRQ as index values which require
4761
* a conversion to dBm and dB respectively. See modem AT
4862
* command reference guide for more information.
@@ -161,6 +175,25 @@ int modem_info_params_init(struct modem_param_info *modem_param);
161175
*/
162176
int modem_info_rsrp_register(rsrp_cb_t cb);
163177

178+
/**
179+
* @brief Initialize collection of connectivity stats
180+
*
181+
* @note The function will reset stats if connectivity stats
182+
* are already initialized/enabled.
183+
*
184+
* @return 0 If the operation was successful.
185+
* Otherwise, a (negative) error code is returned.
186+
*/
187+
int modem_info_connectivity_stats_init(void);
188+
189+
/**
190+
* @brief Disable collection of connectivity stats
191+
*
192+
* @return 0 If the operation was successful.
193+
* Otherwise, a (negative) error code is returned.
194+
*/
195+
int modem_info_connectivity_stats_disable(void);
196+
164197
/** @brief Request the current modem status of any predefined
165198
* information value as a string.
166199
*
@@ -320,6 +353,56 @@ int modem_info_get_temperature(int *val);
320353
*/
321354
int modem_info_get_rsrp(int *val);
322355

356+
/**
357+
* @brief Obtain the connectivity statistics.
358+
*
359+
* Get the total amount of data transmitted and receievd during the collection
360+
* period.
361+
*
362+
* @note Will return bytes = 0 until connectivity stats collection has been
363+
* enabled via AT%XCONNSTAT=1, or with modem_info_connectivity_stats_init().
364+
*
365+
* @param tx_kbytes Pointer to the target variable.
366+
* @param rx_kbytes Pointer to the target variable.
367+
*
368+
* @return 0 if the operation was successful.
369+
* Otherwise, a (negative) error code is returned.
370+
*/
371+
int modem_info_get_connectivity_stats(int *tx_kbytes, int *rx_kbytes);
372+
373+
/**
374+
* @brief Obtain the current band.
375+
*
376+
* @param val Pointer to the target variable.
377+
*
378+
* @return 0 if the operation was successful.
379+
* @return -ENOENT if there is no valid band.
380+
* Otherwise, a (negative) error code is returned.
381+
*/
382+
int modem_info_get_current_band(uint8_t *val);
383+
384+
/**
385+
* @brief Obtain the operator name.
386+
*
387+
* @param buf Pointer to the target buffer.
388+
* @param buf_size Size of target buffer.
389+
*
390+
* @return 0 if the operation was successful.
391+
* Otherwise, a (negative) error code is returned.
392+
*/
393+
int modem_info_get_operator(char *buf, size_t buf_size);
394+
395+
/**
396+
* @brief Obtain the signal-to-noise ratio.
397+
*
398+
* @param val Pointer to the target variable.
399+
*
400+
* @return 0 if the operation was successful.
401+
* @return -ENOENT if there is no valid SNR.
402+
* Otherwise, a (negative) error code is returned.
403+
*/
404+
int modem_info_get_snr(int *val);
405+
323406
/** @} */
324407

325408
#ifdef __cplusplus

lib/modem_info/modem_info.c

Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#include <modem/modem_info.h>
1414
#include <nrf_errno.h>
1515
#include <zephyr/net/socket.h>
16+
#include <zephyr/toolchain.h>
1617
#include <stdint.h>
1718
#include <stdio.h>
1819
#include <string.h>
@@ -43,6 +44,10 @@ LOG_MODULE_REGISTER(modem_info);
4344
#define AT_CMD_IMSI "AT+CIMI"
4445
#define AT_CMD_IMEI "AT+CGSN"
4546
#define AT_CMD_DATE_TIME "AT+CCLK?"
47+
#define AT_CMD_XCONNSTAT "AT%XCONNSTAT?"
48+
#define AT_CMD_XCONNSTAT_ON "AT%%XCONNSTAT=1"
49+
#define AT_CMD_XCONNSTAT_OFF "AT%%XCONNSTAT=0"
50+
#define AT_CMD_XMONITOR "AT%%XMONITOR"
4651
#define AT_CMD_SUCCESS_SIZE 5
4752

4853
#define RSRP_DATA_NAME "rsrp"
@@ -144,6 +149,10 @@ LOG_MODULE_REGISTER(modem_info);
144149
#define HWVER_CMD_STR "HWVERSION"
145150
#define HWVER_FMT_STR "%%%%" HWVER_CMD_STR ": %%%d[^" AT_CMD_RSP_DELIM "]"
146151

152+
#define SHORT_OP_NAME_SIZE_WITHOUT_NULL_TERM 64
153+
BUILD_ASSERT(SHORT_OP_NAME_SIZE_WITHOUT_NULL_TERM == (MODEM_INFO_SHORT_OP_NAME_SIZE - 1),
154+
"Short operator size macros must match");
155+
147156
struct modem_info_data {
148157
const char *cmd;
149158
const char *data_name;
@@ -750,6 +759,30 @@ int modem_info_rsrp_register(rsrp_cb_t cb)
750759
return 0;
751760
}
752761

762+
int modem_info_connectivity_stats_init(void)
763+
{
764+
int err = nrf_modem_at_printf(AT_CMD_XCONNSTAT_ON);
765+
766+
if (err != 0) {
767+
if (err > 0) {
768+
err = nrf_modem_at_err_type(err);
769+
}
770+
}
771+
return err;
772+
}
773+
774+
int modem_info_connectivity_stats_disable(void)
775+
{
776+
int err = nrf_modem_at_printf(AT_CMD_XCONNSTAT_OFF);
777+
778+
if (err != 0) {
779+
if (err > 0) {
780+
err = nrf_modem_at_err_type(err);
781+
}
782+
}
783+
return err;
784+
}
785+
753786
int modem_info_get_fw_uuid(char *buf, size_t buf_size)
754787
{
755788
int ret;
@@ -888,6 +921,92 @@ int modem_info_get_rsrp(int *val)
888921
return 0;
889922
}
890923

924+
int modem_info_get_connectivity_stats(int *tx_kbytes, int *rx_kbytes)
925+
{
926+
if (tx_kbytes == NULL || rx_kbytes == NULL) {
927+
return -EINVAL;
928+
}
929+
930+
int ret = nrf_modem_at_scanf(AT_CMD_XCONNSTAT, "%%XCONNSTAT: %*d,%*d,%d,%d,%*d,%*d",
931+
tx_kbytes, rx_kbytes);
932+
933+
if (ret != 2) {
934+
LOG_ERR("Could not get connectivity stats, error: %d", ret);
935+
return map_nrf_modem_at_scanf_error(ret);
936+
}
937+
938+
return 0;
939+
}
940+
941+
int modem_info_get_current_band(uint8_t *val)
942+
{
943+
if (val == NULL) {
944+
return -EINVAL;
945+
}
946+
947+
int ret = nrf_modem_at_scanf("AT%XCBAND", "%%XCBAND: %u", val);
948+
949+
if (ret != 1) {
950+
LOG_ERR("Could not get band, error: %d", ret);
951+
return map_nrf_modem_at_scanf_error(ret);
952+
}
953+
954+
if (*val == BAND_UNAVAILABLE) {
955+
LOG_WRN("No valid band");
956+
return -ENOENT;
957+
}
958+
959+
return 0;
960+
}
961+
962+
int modem_info_get_operator(char *buf, size_t buf_size)
963+
{
964+
if (buf == NULL || buf_size < MODEM_INFO_SHORT_OP_NAME_SIZE) {
965+
return -EINVAL;
966+
}
967+
968+
int ret = nrf_modem_at_scanf(
969+
"AT%XMONITOR",
970+
"%%XMONITOR: "
971+
"%*u," /* <reg_status> ignored */
972+
"%*[^,]," /* <full_name> ignored */
973+
"\"%" STRINGIFY(SHORT_OP_NAME_SIZE_WITHOUT_NULL_TERM) "[^\"]\",", /* <short_name> */
974+
buf);
975+
976+
if (ret != 1) {
977+
// Warning instead of error because it is not always reported
978+
LOG_WRN("No valid operator");
979+
return map_nrf_modem_at_scanf_error(ret);
980+
}
981+
982+
buf[buf_size - 1] = '\0'; // Null terminate
983+
984+
return 0;
985+
}
986+
987+
int modem_info_get_snr(int *val)
988+
{
989+
if (val == NULL) {
990+
return -EINVAL;
991+
}
992+
993+
int ret = nrf_modem_at_scanf("AT%XSNRSQ?", "%%XSNRSQ: %d,%*d,%*d", val);
994+
995+
if (ret != 1) {
996+
LOG_ERR("Could not get SNR, error: %d", ret);
997+
return map_nrf_modem_at_scanf_error(ret);
998+
}
999+
1000+
if (*val == SNR_UNAVAILABLE) {
1001+
LOG_WRN("No valid SNR");
1002+
return -ENOENT;
1003+
}
1004+
1005+
*val -= SNR_OFFSET_VAL;
1006+
1007+
return 0;
1008+
}
1009+
8911010
int modem_info_init(void)
8921011
{
8931012
int err = 0;

modules/memfault-firmware-sdk/config/memfault_metrics_heartbeat_extra.def

Lines changed: 22 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -5,28 +5,36 @@
55
#endif /* defined(CONFIG_MODEM_INFO) */
66

77
#ifdef CONFIG_MEMFAULT_NCS_STACK_METRICS
8-
MEMFAULT_METRICS_KEY_DEFINE(Ncs_ConnectionPollUnusedStack, kMemfaultMetricType_Unsigned)
9-
MEMFAULT_METRICS_KEY_DEFINE(NcsBtRxUnusedStack, kMemfaultMetricType_Unsigned)
10-
MEMFAULT_METRICS_KEY_DEFINE(NcsBtTxUnusedStack, kMemfaultMetricType_Unsigned)
8+
MEMFAULT_METRICS_KEY_DEFINE(ncs_connection_poll_unused_stack, kMemfaultMetricType_Unsigned)
9+
MEMFAULT_METRICS_KEY_DEFINE(ncs_bt_rx_unused_stack, kMemfaultMetricType_Unsigned)
10+
MEMFAULT_METRICS_KEY_DEFINE(ncs_bt_tx_unused_stack, kMemfaultMetricType_Unsigned)
1111
#endif /* CONFIG_MEMFAULT_NCS_STACK_METRICS */
1212

1313
#ifdef CONFIG_MEMFAULT_NCS_LTE_METRICS
1414

1515
#if defined(CONFIG_MODEM_INFO)
16-
MEMFAULT_METRICS_STRING_KEY_DEFINE(Ncs_LteModemFwVersion, MODEM_INFO_FWVER_SIZE)
16+
MEMFAULT_METRICS_STRING_KEY_DEFINE(ncs_lte_modem_fw_version, MODEM_INFO_FWVER_SIZE)
17+
MEMFAULT_METRICS_STRING_KEY_DEFINE(ncs_lte_operator, MODEM_INFO_SHORT_OP_NAME_SIZE)
18+
MEMFAULT_METRICS_KEY_DEFINE(ncs_lte_snr_decibels, kMemfaultMetricType_Signed)
19+
MEMFAULT_METRICS_KEY_DEFINE(ncs_lte_rsrp_dbm, kMemfaultMetricType_Signed)
20+
MEMFAULT_METRICS_KEY_DEFINE(ncs_lte_tx_kilobytes, kMemfaultMetricType_Unsigned)
21+
MEMFAULT_METRICS_KEY_DEFINE(ncs_lte_rx_kilobytes, kMemfaultMetricType_Unsigned)
22+
MEMFAULT_METRICS_KEY_DEFINE(ncs_lte_band, kMemfaultMetricType_Unsigned)
1723
#endif /* defined(CONFIG_MODEM_INFO) */
1824

19-
MEMFAULT_METRICS_KEY_DEFINE(Ncs_LteTimeToConnect, kMemfaultMetricType_Timer)
20-
MEMFAULT_METRICS_KEY_DEFINE(Ncs_LteConnectionLossCount, kMemfaultMetricType_Unsigned)
21-
MEMFAULT_METRICS_KEY_DEFINE(Ncs_LtePsmTauSec, kMemfaultMetricType_Signed)
22-
MEMFAULT_METRICS_KEY_DEFINE(Ncs_LtePsmActiveTimeSec, kMemfaultMetricType_Signed)
23-
MEMFAULT_METRICS_KEY_DEFINE(Ncs_LteEdrxIntervalMsec, kMemfaultMetricType_Unsigned)
24-
MEMFAULT_METRICS_KEY_DEFINE(Ncs_LteEdrxPtwMsec, kMemfaultMetricType_Unsigned)
25-
MEMFAULT_METRICS_KEY_DEFINE(Ncs_LteMode, kMemfaultMetricType_Unsigned)
25+
MEMFAULT_METRICS_KEY_DEFINE(ncs_lte_time_to_connect_ms, kMemfaultMetricType_Timer)
26+
MEMFAULT_METRICS_KEY_DEFINE(ncs_lte_connection_loss_count, kMemfaultMetricType_Unsigned)
27+
MEMFAULT_METRICS_KEY_DEFINE(ncs_lte_psm_tau_seconds, kMemfaultMetricType_Signed)
28+
MEMFAULT_METRICS_KEY_DEFINE(ncs_lte_psm_active_time_seconds, kMemfaultMetricType_Signed)
29+
MEMFAULT_METRICS_KEY_DEFINE(ncs_lte_edrx_interval_ms, kMemfaultMetricType_Unsigned)
30+
MEMFAULT_METRICS_KEY_DEFINE(ncs_lte_edrx_ptw_ms, kMemfaultMetricType_Unsigned)
31+
MEMFAULT_METRICS_KEY_DEFINE(ncs_lte_mode, kMemfaultMetricType_Unsigned)
32+
MEMFAULT_METRICS_KEY_DEFINE(ncs_lte_on_time_ms, kMemfaultMetricType_Timer)
33+
MEMFAULT_METRICS_KEY_DEFINE(ncs_lte_reset_loop_detected_count, kMemfaultMetricType_Unsigned)
2634
#endif /* CONFIG_MEMFAULT_NCS_LTE_METRICS */
2735

2836
#ifdef CONFIG_MEMFAULT_NCS_BT_METRICS
29-
MEMFAULT_METRICS_KEY_DEFINE(Ncs_BtConnectionTime, kMemfaultMetricType_Timer)
30-
MEMFAULT_METRICS_KEY_DEFINE(Ncs_BtConnectionCount, kMemfaultMetricType_Unsigned)
31-
MEMFAULT_METRICS_KEY_DEFINE(Ncs_BtBondCount, kMemfaultMetricType_Unsigned)
37+
MEMFAULT_METRICS_KEY_DEFINE(ncs_bt_connection_time_ms, kMemfaultMetricType_Timer)
38+
MEMFAULT_METRICS_KEY_DEFINE(ncs_bt_connection_count, kMemfaultMetricType_Unsigned)
39+
MEMFAULT_METRICS_KEY_DEFINE(ncs_bt_bond_count, kMemfaultMetricType_Unsigned)
3240
#endif /* CONFIG_MEMFAULT_NCS_BT_METRICS */

0 commit comments

Comments
 (0)