How to properly activate zephyr logs with network syslog backend to work over LTE-M for nrf9160 custom device?
How to properly activate zephyr logs with network syslog backend to work over LTE-M for nrf9160 custom device?
you need to set up the LTE link using the LTE Link Controller (LTE LC) library and enable the logging infrastructure.
Haven't tested this myself but you can do something like this. In your prj.conf, you need to enable the necessary logging and network configurations
CONFIG_LOG=y CONFIG_LOG_BACKEND_NET=y CONFIG_LOG_DEFAULT_LEVEL=4 CONFIG_NET_SOCKETS=y CONFIG_NET_SOCKETS_POSIX_NAMES=y CONFIG_LTE_LINK_CONTROL=y CONFIG_LOG_BACKEND_NET_SERVER="XXXXXXXX" CONFIG_LOG_BACKEND_NET_PORT=514 # Standard syslog port
Use the LTE Link Controller to connect to the network, which is essential for sending logs. The lte_lc_init_and_connect() function is recommended to initialize and connect to the LTE network. Here's a sample code snippet:
#include <modem/lte_lc.h> #include <zephyr/logging/log.h> #include <zephyr/kernel.h> LOG_MODULE_REGISTER(my_app); void lte_connect(void) { int err = lte_lc_init_and_connect(); if (err) { LOG_ERR("Failed to connect to LTE, error: %d", err); return; } LOG_INF("LTE connected successfully"); } void main(void) { LOG_INF("Starting application..."); lte_connect(); // Application logic while (1) { LOG_INF("Running main loop..."); k_sleep(K_SECONDS(10)); } }
To conserve power, you might want to enable Power Saving Mode (PSM) and Extended Discontinuous Reception (eDRX). These modes help reduce power consumption during idle periods, which is important for battery-powered devices operating over LTE-M. You can request these modes with the following LTE Link Controller APIs
lte_lc_psm_req(true);
lte_lc_edrx_req(true);
Once the LTE-M link is established, the syslog backend configured in Zephyr will automatically forward log messages to the syslog server over the LTE-M connection.
Make sure to set an appropriate log level to avoid flooding the LTE-M network with unnecessary debug messages, especially if the connection is metered.
The suggested example does not work. I slightly supplemented the configuration with new options and created a project for nRF9160-DK. The example code has also been tweaked a bit based on the official Zephyr Syslog example.
CONFIG_BUILD_WITH_TFM=n
CONFIG_HEAP_MEM_POOL_SIZE=20480
CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=4096
CONFIG_MAIN_STACK_SIZE=4096
CONFIG_NEWLIB_LIBC_MIN_REQUIRED_HEAP_SIZE=4096
CONFIG_PRINTK=y
CONFIG_SHELL=y
CONFIG_INIT_STACKS=y
CONFIG_THREAD_STACK_INFO=y
CONFIG_KERNEL_SHELL=y
CONFIG_NETWORKING=y
CONFIG_NET_NATIVE=n
CONFIG_NET_OFFLOAD=y
CONFIG_NET_SOCKETS_OFFLOAD=y
CONFIG_NET_DEFAULT_IF_OFFLOAD=y
CONFIG_NET_IPV6=n
CONFIG_NET_IPV4=y
CONFIG_NET_UDP=y
CONFIG_NET_TCP=y
CONFIG_NET_LOG=y
CONFIG_NRF_MODEM_LIB=y
CONFIG_LTE_AUTO_INIT_AND_CONNECT=n
CONFIG_LTE_NETWORK_MODE_LTE_M_NBIOT_GPS=y
CONFIG_LTE_MODE_PREFERENCE_NBIOT=y
CONFIG_LOG_MODE_DEFERRED=y
CONFIG_LOG_BACKEND_NET_AUTOSTART=n
CONFIG_LOG=y
CONFIG_LOG_BACKEND_NET=y
CONFIG_LOG_DEFAULT_LEVEL=4
CONFIG_NET_SOCKETS=y
CONFIG_NET_SOCKETS_POSIX_NAMES=y
CONFIG_LTE_LINK_CONTROL=y
CONFIG_LOG_BACKEND_NET_SERVER="169.46.82.174:25736"
#include <zephyr.h>
#include <kernel.h>
#include <modem/lte_lc.h>
#include <logging/log.h>
#include <logging/log_backend.h>
#include <logging/log_ctrl.h>
LOG_MODULE_REGISTER(net_syslog_lte, LOG_LEVEL_DBG);
extern const struct log_backend *log_backend_net_get(void);
void begin_syslog(void)
{
LOG_INF("Begin logging to syslog...");
const struct log_backend *log_backend_net = log_backend_net_get();
if (log_backend_net->api->init != NULL) {
log_backend_net->api->init(log_backend_net);
}
log_backend_activate(log_backend_net, NULL);
}
void lte_connect(void)
{
int err = lte_lc_init_and_connect();
if (err)
{
LOG_ERR("Failed to connect to LTE, error: %d", err);
return;
}
LOG_INF("LTE connected successfully");
}
#define SLEEP_BETWEEN_LOG_PRINTS 10 // sec
#define TOTAL_LOG_TIME 30 // sec
void cycle_logs(void)
{
int i, count;
/* Allow some setup time before starting to send data */
k_sleep(K_SECONDS(SLEEP_BETWEEN_LOG_PRINTS));
count = TOTAL_LOG_TIME / SLEEP_BETWEEN_LOG_PRINTS;
i = count;
do
{
LOG_ERR("Error message (%d)", i);
LOG_WRN("Warning message (%d)", i);
LOG_INF("Info message (%d)", i);
LOG_DBG("Debug message (%d)", i);
k_sleep(K_SECONDS(SLEEP_BETWEEN_LOG_PRINTS));
} while (--i);
LOG_DBG("Stopped after %d msg", count);
}
void main(void)
{
LOG_INF("Starting application...");
lte_connect();
begin_syslog();
cycle_logs();
while (1)
{
k_sleep(K_SECONDS(10));
}
}
Unfortunately, debugging didn't clear anything up. But there is a suspicion that the network interface for Syslog through LTE does not work. I tested the official Zephyr example on a device with built-in Ethernet and everything works there.
The suggested example does not work. I slightly supplemented the configuration with new options and created a project for nRF9160-DK. The example code has also been tweaked a bit based on the official Zephyr Syslog example.
CONFIG_BUILD_WITH_TFM=n
CONFIG_HEAP_MEM_POOL_SIZE=20480
CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=4096
CONFIG_MAIN_STACK_SIZE=4096
CONFIG_NEWLIB_LIBC_MIN_REQUIRED_HEAP_SIZE=4096
CONFIG_PRINTK=y
CONFIG_SHELL=y
CONFIG_INIT_STACKS=y
CONFIG_THREAD_STACK_INFO=y
CONFIG_KERNEL_SHELL=y
CONFIG_NETWORKING=y
CONFIG_NET_NATIVE=n
CONFIG_NET_OFFLOAD=y
CONFIG_NET_SOCKETS_OFFLOAD=y
CONFIG_NET_DEFAULT_IF_OFFLOAD=y
CONFIG_NET_IPV6=n
CONFIG_NET_IPV4=y
CONFIG_NET_UDP=y
CONFIG_NET_TCP=y
CONFIG_NET_LOG=y
CONFIG_NRF_MODEM_LIB=y
CONFIG_LTE_AUTO_INIT_AND_CONNECT=n
CONFIG_LTE_NETWORK_MODE_LTE_M_NBIOT_GPS=y
CONFIG_LTE_MODE_PREFERENCE_NBIOT=y
CONFIG_LOG_MODE_DEFERRED=y
CONFIG_LOG_BACKEND_NET_AUTOSTART=n
CONFIG_LOG=y
CONFIG_LOG_BACKEND_NET=y
CONFIG_LOG_DEFAULT_LEVEL=4
CONFIG_NET_SOCKETS=y
CONFIG_NET_SOCKETS_POSIX_NAMES=y
CONFIG_LTE_LINK_CONTROL=y
CONFIG_LOG_BACKEND_NET_SERVER="169.46.82.174:25736"
#include <zephyr.h>
#include <kernel.h>
#include <modem/lte_lc.h>
#include <logging/log.h>
#include <logging/log_backend.h>
#include <logging/log_ctrl.h>
LOG_MODULE_REGISTER(net_syslog_lte, LOG_LEVEL_DBG);
extern const struct log_backend *log_backend_net_get(void);
void begin_syslog(void)
{
LOG_INF("Begin logging to syslog...");
const struct log_backend *log_backend_net = log_backend_net_get();
if (log_backend_net->api->init != NULL) {
log_backend_net->api->init(log_backend_net);
}
log_backend_activate(log_backend_net, NULL);
}
void lte_connect(void)
{
int err = lte_lc_init_and_connect();
if (err)
{
LOG_ERR("Failed to connect to LTE, error: %d", err);
return;
}
LOG_INF("LTE connected successfully");
}
#define SLEEP_BETWEEN_LOG_PRINTS 10 // sec
#define TOTAL_LOG_TIME 30 // sec
void cycle_logs(void)
{
int i, count;
/* Allow some setup time before starting to send data */
k_sleep(K_SECONDS(SLEEP_BETWEEN_LOG_PRINTS));
count = TOTAL_LOG_TIME / SLEEP_BETWEEN_LOG_PRINTS;
i = count;
do
{
LOG_ERR("Error message (%d)", i);
LOG_WRN("Warning message (%d)", i);
LOG_INF("Info message (%d)", i);
LOG_DBG("Debug message (%d)", i);
k_sleep(K_SECONDS(SLEEP_BETWEEN_LOG_PRINTS));
} while (--i);
LOG_DBG("Stopped after %d msg", count);
}
void main(void)
{
LOG_INF("Starting application...");
lte_connect();
begin_syslog();
cycle_logs();
while (1)
{
k_sleep(K_SECONDS(10));
}
}
Unfortunately, debugging didn't clear anything up. But there is a suspicion that the network interface for Syslog through LTE does not work. I tested the official Zephyr example on a device with built-in Ethernet and everything works there.