From 4e0f0849d6e7997cbc128d998ba824d6ac3e7181 Mon Sep 17 00:00:00 2001 From: xengineering Date: Sun, 13 Apr 2025 08:27:20 +0200 Subject: fw: app: Enable settings with NVS backend --- fw/app/src/settings.c | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 fw/app/src/settings.c (limited to 'fw/app/src/settings.c') diff --git a/fw/app/src/settings.c b/fw/app/src/settings.c new file mode 100644 index 0000000..11cc162 --- /dev/null +++ b/fw/app/src/settings.c @@ -0,0 +1,26 @@ +/* + * This Source Code Form is subject to the terms of the Mozilla Public License, + * v. 2.0. If a copy of the MPL was not distributed with this file, You can + * obtain one at https://mozilla.org/MPL/2.0/. + */ + + +#include +#include +#include + + +LOG_MODULE_DECLARE(settings); + + +int init_settings(void) { + int ret = settings_subsys_init(); + if (ret < 0) { + LOG_ERR("Subsystem init failed (%d)", ret); + return ret; + } + LOG_INF("Subsystem initialized"); + + return 0; +} +SYS_INIT(init_settings, APPLICATION, 50); -- cgit v1.2.3-70-g09d2 From 698832f42c11d1df2b955de37b6b130c980dadce Mon Sep 17 00:00:00 2001 From: xengineering Date: Tue, 15 Apr 2025 17:14:06 +0200 Subject: fw: app: syslog: Make target IP configurable --- fw/app/prj.conf | 1 + fw/app/src/settings.c | 9 +++++++- fw/app/src/syslog.c | 57 +++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 66 insertions(+), 1 deletion(-) (limited to 'fw/app/src/settings.c') diff --git a/fw/app/prj.conf b/fw/app/prj.conf index cd487f3..3258c0f 100644 --- a/fw/app/prj.conf +++ b/fw/app/prj.conf @@ -53,5 +53,6 @@ CONFIG_NVS=y CONFIG_NVS_DATA_CRC=y CONFIG_SETTINGS=y +CONFIG_SETTINGS_RUNTIME=y CONFIG_SETTINGS_NVS=y CONFIG_SETTINGS_SHELL=y diff --git a/fw/app/src/settings.c b/fw/app/src/settings.c index 11cc162..916c7ad 100644 --- a/fw/app/src/settings.c +++ b/fw/app/src/settings.c @@ -21,6 +21,13 @@ int init_settings(void) { } LOG_INF("Subsystem initialized"); + ret = settings_load(); + if (ret < 0) { + LOG_ERR("Failed to load settings (%d)", ret); + return ret; + } + LOG_INF("Loaded settings"); + return 0; } -SYS_INIT(init_settings, APPLICATION, 50); +SYS_INIT(init_settings, APPLICATION, 40); diff --git a/fw/app/src/syslog.c b/fw/app/src/syslog.c index e19a196..6dc0bd6 100644 --- a/fw/app/src/syslog.c +++ b/fw/app/src/syslog.c @@ -4,8 +4,10 @@ * obtain one at https://mozilla.org/MPL/2.0/. */ +#include #include +#include #include #include #include @@ -14,6 +16,8 @@ #include #include #include +#include +#include #ifdef CONFIG_IOT_CONTACT_NETWORK_HACK #include @@ -23,9 +27,11 @@ LOG_MODULE_REGISTER(syslog); #define NETWORK_BUG_DELAY K_MSEC(4000) #define L4_EVENT_MASK (NET_EVENT_L4_CONNECTED | NET_EVENT_L4_DISCONNECTED) +#define IPV6_STRLEN_MAX 40 // including '\0' struct net_mgmt_event_callback l4_cb; static K_SEM_DEFINE(network_connected, 0, 1); +static char target_ip[IPV6_STRLEN_MAX] = CONFIG_LOG_BACKEND_NET_SERVER; void l4_event_handler( struct net_mgmt_event_callback *cb, @@ -79,6 +85,10 @@ int init_syslog(void) /* flush log messages to ensure first syslog message is reproducible */ while (log_process()); log_backend_init(backend); + LOG_INF("Setting syslog target to: '%s'", target_ip); + if (log_backend_net_set_addr(target_ip) == false) { + LOG_ERR("Could not set target IP to '%s'", target_ip); + } log_backend_enable(backend, backend->cb->ctx, CONFIG_LOG_MAX_LEVEL); LOG_INF("Syslog backend enabled"); } else { @@ -88,3 +98,50 @@ int init_syslog(void) return 0; } SYS_INIT(init_syslog, APPLICATION, 50); + +int syslog_handle_set(const char *name, size_t len, settings_read_cb read_cb, + void *cb_arg) +{ + const char* next = NULL; + + if (settings_name_steq(name, "target/ip", &next) && !next) { + memset(target_ip, '\0', sizeof(target_ip)); + ssize_t ret = read_cb(cb_arg, target_ip, MIN(sizeof(target_ip) - 1, len)); + if (ret < 0) { + LOG_ERR("Failed to read syslog/target/ip setting (%d)", ret); + return (int)ret; + } + LOG_INF("Setting target IP address to '%s'", target_ip); + return 0; + } + + return 0; +} + +int syslog_handle_commit(void) +{ + LOG_WRN("Settings commit not implemented"); + return 0; +} + +int syslog_handle_export(int (*cb)(const char *name, const void *value, + size_t val_len)) +{ + LOG_WRN("Settings export not implemented"); + return 0; +} + +int syslog_handle_get(const char *name, char *val, int val_len_max) +{ + LOG_WRN("Settings get not implemented"); + return 0; +} + +SETTINGS_STATIC_HANDLER_DEFINE( + syslog_settings_handler, + "syslog", + syslog_handle_get, + syslog_handle_set, + syslog_handle_commit, + syslog_handle_export +); -- cgit v1.2.3-70-g09d2 From 0bff2eea39c11b5ad2e762325abeb1457ae0fd7e Mon Sep 17 00:00:00 2001 From: xengineering Date: Tue, 15 Apr 2025 18:06:32 +0200 Subject: fw: app: syslog: Implement commit target --- fw/app/src/settings.c | 2 +- fw/app/src/syslog.c | 16 ++++++++-------- 2 files changed, 9 insertions(+), 9 deletions(-) (limited to 'fw/app/src/settings.c') diff --git a/fw/app/src/settings.c b/fw/app/src/settings.c index 916c7ad..799322e 100644 --- a/fw/app/src/settings.c +++ b/fw/app/src/settings.c @@ -30,4 +30,4 @@ int init_settings(void) { return 0; } -SYS_INIT(init_settings, APPLICATION, 40); +SYS_INIT(init_settings, APPLICATION, 50); diff --git a/fw/app/src/syslog.c b/fw/app/src/syslog.c index 6dc0bd6..8fe2412 100644 --- a/fw/app/src/syslog.c +++ b/fw/app/src/syslog.c @@ -85,10 +85,6 @@ int init_syslog(void) /* flush log messages to ensure first syslog message is reproducible */ while (log_process()); log_backend_init(backend); - LOG_INF("Setting syslog target to: '%s'", target_ip); - if (log_backend_net_set_addr(target_ip) == false) { - LOG_ERR("Could not set target IP to '%s'", target_ip); - } log_backend_enable(backend, backend->cb->ctx, CONFIG_LOG_MAX_LEVEL); LOG_INF("Syslog backend enabled"); } else { @@ -97,7 +93,7 @@ int init_syslog(void) return 0; } -SYS_INIT(init_syslog, APPLICATION, 50); +SYS_INIT(init_syslog, APPLICATION, 40); int syslog_handle_set(const char *name, size_t len, settings_read_cb read_cb, void *cb_arg) @@ -108,10 +104,10 @@ int syslog_handle_set(const char *name, size_t len, settings_read_cb read_cb, memset(target_ip, '\0', sizeof(target_ip)); ssize_t ret = read_cb(cb_arg, target_ip, MIN(sizeof(target_ip) - 1, len)); if (ret < 0) { - LOG_ERR("Failed to read syslog/target/ip setting (%d)", ret); + LOG_ERR("Failed to set target (%d)", ret); return (int)ret; } - LOG_INF("Setting target IP address to '%s'", target_ip); + LOG_INF("Set target to '%s'", target_ip); return 0; } @@ -120,7 +116,11 @@ int syslog_handle_set(const char *name, size_t len, settings_read_cb read_cb, int syslog_handle_commit(void) { - LOG_WRN("Settings commit not implemented"); + if (log_backend_net_set_addr(target_ip) == false) { + LOG_ERR("Could not commit target to '%s'", target_ip); + } + LOG_INF("Committed new target: '%s'", target_ip); + return 0; } -- cgit v1.2.3-70-g09d2 From f4faa103108356bcf53fb7c8829e95f012b21a4a Mon Sep 17 00:00:00 2001 From: xengineering Date: Tue, 15 Apr 2025 22:12:54 +0200 Subject: fw: app: http: Add working GET /settings.json --- fw/app/prj.conf | 2 ++ fw/app/src/http.c | 14 +++++++++++--- fw/app/src/settings.c | 29 +++++++++++++++++++++++++++++ fw/app/src/settings.h | 11 +++++++++++ fw/app/src/syslog.c | 11 +++++++++-- 5 files changed, 62 insertions(+), 5 deletions(-) create mode 100644 fw/app/src/settings.h (limited to 'fw/app/src/settings.c') diff --git a/fw/app/prj.conf b/fw/app/prj.conf index 10de150..4981bea 100644 --- a/fw/app/prj.conf +++ b/fw/app/prj.conf @@ -55,3 +55,5 @@ CONFIG_SETTINGS=y CONFIG_SETTINGS_RUNTIME=y CONFIG_SETTINGS_NVS=y CONFIG_SETTINGS_SHELL=y + +CONFIG_GNU_C_EXTENSIONS=y diff --git a/fw/app/src/http.c b/fw/app/src/http.c index 081629b..83a3568 100644 --- a/fw/app/src/http.c +++ b/fw/app/src/http.c @@ -13,6 +13,7 @@ #include #include +#include "settings.h" #include "ws.h" @@ -98,9 +99,16 @@ static int settings_handler( struct http_response_ctx *response_ctx, void *user_data ) { - static const char dummy[] = "{\"syslog\":{\"target\":{\"ip\":\"fe80::1\"}}}\n"; - response_ctx->body = (const uint8_t *)dummy; - response_ctx->body_len = sizeof(dummy) - 1; + static char buffer[100]; + + int ret = settings_to_json(buffer, sizeof(buffer)); + if (ret < 0) { + LOG_ERR("Could not serialize payload for settings request"); + return ret; + } + + response_ctx->body = (const uint8_t *)buffer; + response_ctx->body_len = ret; response_ctx->final_chunk = true; response_ctx->status = HTTP_200_OK; diff --git a/fw/app/src/settings.c b/fw/app/src/settings.c index 799322e..89f2f88 100644 --- a/fw/app/src/settings.c +++ b/fw/app/src/settings.c @@ -5,10 +5,14 @@ */ +#include + #include #include #include +#include "settings.h" + LOG_MODULE_DECLARE(settings); @@ -31,3 +35,28 @@ int init_settings(void) { return 0; } SYS_INIT(init_settings, APPLICATION, 50); + +int settings_to_json(void *buffer, size_t len) +{ + static const char format[] = "{\"syslog\":{\"target\":{\"ip\":\"%s\"}}}\n"; + + char ip[100]; + int ret = settings_runtime_get("syslog/target/ip", ip, sizeof(ip)); + if (ret < 0) { + LOG_ERR("Failed to get runtime setting syslog/target/ip (%d)", ret); + return ret; + } + + ret = snprintf(buffer, len, format, ip); + + if (ret >= len) { + LOG_ERR("Buffer too small to serialize settings as JSON"); + return -ENOMEM; + } + + if (ret < 0) { + LOG_ERR("Failed to serialize settings as JSON"); + } + + return ret; +} diff --git a/fw/app/src/settings.h b/fw/app/src/settings.h new file mode 100644 index 0000000..a5cf2ac --- /dev/null +++ b/fw/app/src/settings.h @@ -0,0 +1,11 @@ +/* + * This Source Code Form is subject to the terms of the Mozilla Public License, + * v. 2.0. If a copy of the MPL was not distributed with this file, You can + * obtain one at https://mozilla.org/MPL/2.0/. + */ + + +#include + + +int settings_to_json(void *buffer, size_t data); diff --git a/fw/app/src/syslog.c b/fw/app/src/syslog.c index 47b2edb..700547b 100644 --- a/fw/app/src/syslog.c +++ b/fw/app/src/syslog.c @@ -7,6 +7,7 @@ #include #include #include +#include #include #include @@ -33,7 +34,7 @@ LOG_MODULE_REGISTER(syslog); struct net_mgmt_event_callback l4_cb; static K_SEM_DEFINE(network_connected, 0, 1); -static char target_ip[IPV6_STRLEN_MAX] = "2001:db8::2"; +static char target_ip[IPV6_STRLEN_MAX + 1] = "2001:db8::2"; void l4_event_handler( struct net_mgmt_event_callback *cb, @@ -145,7 +146,13 @@ int syslog_handle_export(int (*cb)(const char *name, const void *value, int syslog_handle_get(const char *name, char *val, int val_len_max) { - LOG_WRN("Settings get not implemented"); + const char* next = NULL; + + if (settings_name_steq(name, "target/ip", &next) && !next) { + size_t len = strnlen(target_ip, sizeof(target_ip)); + memcpy(val, target_ip, MIN(len, val_len_max)); + } + return 0; } -- cgit v1.2.3-70-g09d2 From 993996ab2b9dc7332d06453e2de7315b06ce2458 Mon Sep 17 00:00:00 2001 From: xengineering Date: Wed, 16 Apr 2025 21:58:20 +0200 Subject: fw: app: Encode settings with JSON lib --- fw/app/prj.conf | 2 ++ fw/app/src/http.c | 15 +++++++++++++-- fw/app/src/settings.c | 41 ++++++++++++++++++++++++++++------------- fw/app/src/settings.h | 21 +++++++++++++++++++++ fw/app/src/syslog.c | 3 ++- 5 files changed, 66 insertions(+), 16 deletions(-) (limited to 'fw/app/src/settings.c') diff --git a/fw/app/prj.conf b/fw/app/prj.conf index 4981bea..6589ec0 100644 --- a/fw/app/prj.conf +++ b/fw/app/prj.conf @@ -57,3 +57,5 @@ CONFIG_SETTINGS_NVS=y CONFIG_SETTINGS_SHELL=y CONFIG_GNU_C_EXTENSIONS=y + +CONFIG_JSON_LIBRARY=y diff --git a/fw/app/src/http.c b/fw/app/src/http.c index 83a3568..1c24490 100644 --- a/fw/app/src/http.c +++ b/fw/app/src/http.c @@ -5,6 +5,7 @@ */ +#include #include #include @@ -101,14 +102,24 @@ static int settings_handler( ) { static char buffer[100]; - int ret = settings_to_json(buffer, sizeof(buffer)); + int ret = settings_to_json(buffer, sizeof(buffer) - 1); if (ret < 0) { LOG_ERR("Could not serialize payload for settings request"); return ret; } + size_t len = strnlen(buffer, sizeof(buffer)); + if (len + 2 > sizeof(buffer)) { + LOG_ERR("Settings JSON requires %d octets but buffer has only %d", + len + 2, sizeof(buffer)); + return -ENOMEM; + } + + buffer[len] = '\n'; + buffer[len + 1] = '\0'; + response_ctx->body = (const uint8_t *)buffer; - response_ctx->body_len = ret; + response_ctx->body_len = len + 1; response_ctx->final_chunk = true; response_ctx->status = HTTP_200_OK; diff --git a/fw/app/src/settings.c b/fw/app/src/settings.c index 89f2f88..4b2c248 100644 --- a/fw/app/src/settings.c +++ b/fw/app/src/settings.c @@ -4,9 +4,9 @@ * obtain one at https://mozilla.org/MPL/2.0/. */ +#include -#include - +#include #include #include #include @@ -36,27 +36,42 @@ int init_settings(void) { } SYS_INIT(init_settings, APPLICATION, 50); +static const struct json_obj_descr settings_syslog_target_descr[] = { + JSON_OBJ_DESCR_PRIM(struct settings_syslog_target, ip, JSON_TOK_STRING), +}; + +static const struct json_obj_descr settings_syslog_descr[] = { + JSON_OBJ_DESCR_OBJECT(struct settings_syslog, target, settings_syslog_target_descr), +}; + +static const struct json_obj_descr settings_descr[] = { + JSON_OBJ_DESCR_OBJECT(struct settings, syslog, settings_syslog_descr), +}; + int settings_to_json(void *buffer, size_t len) { - static const char format[] = "{\"syslog\":{\"target\":{\"ip\":\"%s\"}}}\n"; + struct settings settings = {0,}; + settings.syslog.target.ip = (char *)settings.syslog.target.ip_array; - char ip[100]; - int ret = settings_runtime_get("syslog/target/ip", ip, sizeof(ip)); + int ret = settings_runtime_get("syslog/target/ip", + settings.syslog.target.ip_array, + sizeof(settings.syslog.target.ip_array)); if (ret < 0) { LOG_ERR("Failed to get runtime setting syslog/target/ip (%d)", ret); return ret; } - ret = snprintf(buffer, len, format, ip); - - if (ret >= len) { - LOG_ERR("Buffer too small to serialize settings as JSON"); - return -ENOMEM; - } - + ret = json_obj_encode_buf( + settings_descr, + ARRAY_SIZE(settings_descr), + &settings, + buffer, + len + ); if (ret < 0) { LOG_ERR("Failed to serialize settings as JSON"); + return ret; } - return ret; + return 0; } diff --git a/fw/app/src/settings.h b/fw/app/src/settings.h index a5cf2ac..290d1ff 100644 --- a/fw/app/src/settings.h +++ b/fw/app/src/settings.h @@ -4,8 +4,29 @@ * obtain one at https://mozilla.org/MPL/2.0/. */ +#ifndef SRC_SETTINGS_H +#define SRC_SETTINGS_H #include +#include + +#define IPV6_STRLEN_MAX 39 // excluding '\0' + + +struct settings_syslog_target { + char ip_array[IPV6_STRLEN_MAX]; + char *ip; /* Zephyr's JSON lib does not work with arrays directly */ +}; + +struct settings_syslog { + struct settings_syslog_target target; +}; + +struct settings { + struct settings_syslog syslog; +}; int settings_to_json(void *buffer, size_t data); + +#endif // !SRC_SETTINGS_H diff --git a/fw/app/src/syslog.c b/fw/app/src/syslog.c index 700547b..22aa034 100644 --- a/fw/app/src/syslog.c +++ b/fw/app/src/syslog.c @@ -25,11 +25,12 @@ #include #endif // CONFIG_IOT_CONTACT_NETWORK_HACK +#include "settings.h" + LOG_MODULE_REGISTER(syslog); #define NETWORK_BUG_DELAY K_MSEC(4000) #define L4_EVENT_MASK (NET_EVENT_L4_CONNECTED | NET_EVENT_L4_DISCONNECTED) -#define IPV6_STRLEN_MAX 39 // excluding '\0' #define SYSLOG_TARGET_PORT 514 struct net_mgmt_event_callback l4_cb; -- cgit v1.2.3-70-g09d2