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/CMakeLists.txt | 1 + fw/app/prj.conf | 12 ++++++++++++ fw/app/src/settings.c | 26 ++++++++++++++++++++++++++ 3 files changed, 39 insertions(+) create mode 100644 fw/app/src/settings.c diff --git a/fw/app/CMakeLists.txt b/fw/app/CMakeLists.txt index 1a63b77..de1c418 100644 --- a/fw/app/CMakeLists.txt +++ b/fw/app/CMakeLists.txt @@ -19,6 +19,7 @@ target_sources(app "${CMAKE_CURRENT_SOURCE_DIR}/src/http.c" "${CMAKE_CURRENT_SOURCE_DIR}/src/ws.c" "${CMAKE_CURRENT_SOURCE_DIR}/src/heart.c" + "${CMAKE_CURRENT_SOURCE_DIR}/src/settings.c" ) target_sources_ifdef( diff --git a/fw/app/prj.conf b/fw/app/prj.conf index 11dc04f..cd487f3 100644 --- a/fw/app/prj.conf +++ b/fw/app/prj.conf @@ -43,3 +43,15 @@ CONFIG_ZVFS_POLL_MAX=32 CONFIG_ZBUS=y CONFIG_ZBUS_MSG_SUBSCRIBER=y CONFIG_HEAP_MEM_POOL_SIZE=2048 + +CONFIG_FLASH=y +CONFIG_FLASH_MAP=y + +CONFIG_MPU_ALLOW_FLASH_WRITE=y + +CONFIG_NVS=y +CONFIG_NVS_DATA_CRC=y + +CONFIG_SETTINGS=y +CONFIG_SETTINGS_NVS=y +CONFIG_SETTINGS_SHELL=y 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(-) 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(-) 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 409348732bb4cd6ec0c06c4b38f26f528313ffdf Mon Sep 17 00:00:00 2001 From: xengineering Date: Tue, 15 Apr 2025 18:33:31 +0200 Subject: fw: app: syslog: Put only IP into syslog/target/ip The old format contained `[]:`. Nevertheless the format should be as strict as possible. Thus only the IP is used in the setting. --- fw/app/src/syslog.c | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/fw/app/src/syslog.c b/fw/app/src/syslog.c index 8fe2412..c3b5815 100644 --- a/fw/app/src/syslog.c +++ b/fw/app/src/syslog.c @@ -6,6 +6,7 @@ #include #include +#include #include #include @@ -27,7 +28,8 @@ 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' +#define IPV6_STRLEN_MAX 39 // excluding '\0' +#define SYSLOG_TARGET_PORT 514 struct net_mgmt_event_callback l4_cb; static K_SEM_DEFINE(network_connected, 0, 1); @@ -104,10 +106,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 set target (%d)", ret); + LOG_ERR("Failed to set target IP (%d)", ret); return (int)ret; } - LOG_INF("Set target to '%s'", target_ip); + LOG_INF("Set target IP to '%s'", target_ip); return 0; } @@ -116,10 +118,20 @@ int syslog_handle_set(const char *name, size_t len, settings_read_cb read_cb, int syslog_handle_commit(void) { - if (log_backend_net_set_addr(target_ip) == false) { - LOG_ERR("Could not commit target to '%s'", target_ip); + char target[IPV6_STRLEN_MAX + 9]; // 9 for brackets, colon, port and \0 + + int ret = snprintf(target, sizeof(target), "[%s]:%d", target_ip, + SYSLOG_TARGET_PORT); + if (ret < 0) { + LOG_ERR("Failed to format target based on ip and port (%d)", ret); + return ret; + } + + if (log_backend_net_set_addr(target) == false) { + LOG_ERR("Could not commit settings"); + return -EINVAL; } - LOG_INF("Committed new target: '%s'", target_ip); + LOG_INF("Committed settings"); return 0; } -- cgit v1.2.3-70-g09d2 From 11967efab73c43bc5b0c6da33c140dbab7baefa7 Mon Sep 17 00:00:00 2001 From: xengineering Date: Tue, 15 Apr 2025 18:41:27 +0200 Subject: fw: app: syslog: Stop supporting CONFIG_LOG_BACKEND_NET_SERVER From now on the mixed format with IP and port is not supported. The settings system should keep them separate and first only the IP is configurable. Supporting this Kconfig option too is annoying and not necessary. --- fw/app/prj.conf | 1 - fw/app/src/syslog.c | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/fw/app/prj.conf b/fw/app/prj.conf index 3258c0f..10de150 100644 --- a/fw/app/prj.conf +++ b/fw/app/prj.conf @@ -21,7 +21,6 @@ CONFIG_NET_IF_UNICAST_IPV6_ADDR_COUNT=4 CONFIG_LOG=y CONFIG_LOG_BACKEND_NET=y -CONFIG_LOG_BACKEND_NET_SERVER="[2001:db8::2]:514" CONFIG_LOG_BACKEND_NET_AUTOSTART=n CONFIG_LOG_MODE_DEFERRED=y diff --git a/fw/app/src/syslog.c b/fw/app/src/syslog.c index c3b5815..47b2edb 100644 --- a/fw/app/src/syslog.c +++ b/fw/app/src/syslog.c @@ -33,7 +33,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] = CONFIG_LOG_BACKEND_NET_SERVER; +static char target_ip[IPV6_STRLEN_MAX] = "2001:db8::2"; void l4_event_handler( struct net_mgmt_event_callback *cb, -- cgit v1.2.3-70-g09d2 From d25c8e08ce6a977977e38365ace9af16acf09195 Mon Sep 17 00:00:00 2001 From: xengineering Date: Tue, 15 Apr 2025 21:30:26 +0200 Subject: fw: app: http: Add dummy GET /settings.json --- fw/app/src/http.c | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/fw/app/src/http.c b/fw/app/src/http.c index 08b59c1..081629b 100644 --- a/fw/app/src/http.c +++ b/fw/app/src/http.c @@ -91,6 +91,31 @@ static struct http_resource_detail_dynamic favicon_resource_detail = { .user_data = NULL, }; +static int settings_handler( + struct http_client_ctx *client, + enum http_data_status status, + const struct http_request_ctx *request_ctx, + 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; + response_ctx->final_chunk = true; + response_ctx->status = HTTP_200_OK; + + return 0; +} + +static struct http_resource_detail_dynamic settings_resource_detail = { + .common = { + .type = HTTP_RESOURCE_TYPE_DYNAMIC, + .bitmask_of_supported_http_methods = BIT(HTTP_GET), + }, + .cb = settings_handler, + .user_data = NULL, +}; + static uint8_t websocket_read_buffer[1024]; struct http_resource_detail_websocket websocket_resource_detail = { @@ -112,6 +137,7 @@ HTTP_RESOURCE_DEFINE(websocket_resource, http_service, "/", &websocket_resource_ HTTP_RESOURCE_DEFINE(favicon_resource, http_service, "/favicon.ico", &favicon_resource_detail); HTTP_RESOURCE_DEFINE(css_resource, http_service, "/simple.css", &css_resource_detail); HTTP_RESOURCE_DEFINE(js_resource, http_service, "/iot-contact.js", &js_resource_detail); +HTTP_RESOURCE_DEFINE(settings_resource, http_service, "/settings.json", &settings_resource_detail); int init_http_server(void) { LOG_DBG("Starting HTTP server"); -- 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 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(-) 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 From 197353de06d6504cea62b9c2dbeedb384750b888 Mon Sep 17 00:00:00 2001 From: xengineering Date: Sun, 20 Apr 2025 15:12:50 +0200 Subject: fw: app: http: Set settings content type to text/json --- fw/app/src/http.c | 1 + 1 file changed, 1 insertion(+) diff --git a/fw/app/src/http.c b/fw/app/src/http.c index 1c24490..88cf579 100644 --- a/fw/app/src/http.c +++ b/fw/app/src/http.c @@ -130,6 +130,7 @@ static struct http_resource_detail_dynamic settings_resource_detail = { .common = { .type = HTTP_RESOURCE_TYPE_DYNAMIC, .bitmask_of_supported_http_methods = BIT(HTTP_GET), + .content_type = "text/json", }, .cb = settings_handler, .user_data = NULL, -- cgit v1.2.3-70-g09d2 From 60e839846609b0db54304563c779335fa8253343 Mon Sep 17 00:00:00 2001 From: xengineering Date: Sun, 20 Apr 2025 17:07:23 +0200 Subject: fw: app: http: Refactor settings handler --- fw/app/src/http.c | 19 ++++++++++++------- fw/app/src/settings.h | 1 + 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/fw/app/src/http.c b/fw/app/src/http.c index 88cf579..f9016c1 100644 --- a/fw/app/src/http.c +++ b/fw/app/src/http.c @@ -100,26 +100,31 @@ static int settings_handler( struct http_response_ctx *response_ctx, void *user_data ) { - static char buffer[100]; + static char buffer[SETTINGS_JSON_MAX_LEN]; - int ret = settings_to_json(buffer, sizeof(buffer) - 1); + int ret = settings_to_json(buffer, sizeof(buffer)); 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)); + if (len >= sizeof(buffer)) { + LOG_ERR("End of settings JSON string not found (strnlen returned %d)", + sizeof(buffer)); return -ENOMEM; } - buffer[len] = '\n'; + if (sizeof(buffer) < len + 2) { + LOG_ERR("Settings JSON buffer too small to hold \\n and \\0"); + return -ENOMEM; + } + buffer[len + 0] = '\n'; buffer[len + 1] = '\0'; + len += 1; response_ctx->body = (const uint8_t *)buffer; - response_ctx->body_len = len + 1; + response_ctx->body_len = len; response_ctx->final_chunk = true; response_ctx->status = HTTP_200_OK; diff --git a/fw/app/src/settings.h b/fw/app/src/settings.h index 290d1ff..8c7b4e3 100644 --- a/fw/app/src/settings.h +++ b/fw/app/src/settings.h @@ -12,6 +12,7 @@ #include #define IPV6_STRLEN_MAX 39 // excluding '\0' +#define SETTINGS_JSON_MAX_LEN (IPV6_STRLEN_MAX + 50) struct settings_syslog_target { -- cgit v1.2.3-70-g09d2 From 184a41809c66868992c90ce9d420b8e4dc46253b Mon Sep 17 00:00:00 2001 From: xengineering Date: Sun, 20 Apr 2025 13:27:14 +0200 Subject: fw: app: Enable CONFIG_NO_OPTIMIZATIONS This disables compiler optimization and allows easier debugging. --- fw/app/prj.conf | 2 ++ 1 file changed, 2 insertions(+) diff --git a/fw/app/prj.conf b/fw/app/prj.conf index 6589ec0..f1b39a9 100644 --- a/fw/app/prj.conf +++ b/fw/app/prj.conf @@ -59,3 +59,5 @@ CONFIG_SETTINGS_SHELL=y CONFIG_GNU_C_EXTENSIONS=y CONFIG_JSON_LIBRARY=y + +CONFIG_NO_OPTIMIZATIONS=y -- cgit v1.2.3-70-g09d2