diff --git a/CMakeLists.txt b/CMakeLists.txt index 413097a..d2c2ef4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -17,6 +17,7 @@ target_include_directories(app PRIVATE target_sources(app PRIVATE src/main.c + src/app_nvs.c src/parser.c src/power_control.c src/ble/ble_service.c diff --git a/prj.conf b/prj.conf index f776646..0f2aaf9 100644 --- a/prj.conf +++ b/prj.conf @@ -68,6 +68,8 @@ CONFIG_BT_RX_STACK_SIZE=4096 # 애플리케이션이 MCUboot 환경(부트로더)에서 동작(MCUboot: FW 교체 판단, 서명 검증) CONFIG_BOOTLOADER_MCUBOOT=y CONFIG_ZCBOR=y + +# 내부 Flash Meory 활성화 CONFIG_FLASH=y CONFIG_FLASH_MAP=y diff --git a/src/app_nvs.c b/src/app_nvs.c new file mode 100644 index 0000000..0bb02e1 --- /dev/null +++ b/src/app_nvs.c @@ -0,0 +1,222 @@ +/******************************************************************************* + * @file app_nvs.c + * @brief Application persistent settings stored through Zephyr NVS/settings + ******************************************************************************/ +#include +#include +#if IS_ENABLED(CONFIG_SETTINGS) +#include +#endif +#include +#include + +#include "app_nvs.h" +#include "main.h" +#include "debug_print.h" + +#define APP_NVS_SETTINGS_NAME "vesiscan" +#define APP_NVS_KEY_PIEZO "piezo" +#define APP_NVS_KEY_HW_NO "hw" +#define APP_NVS_KEY_SERIAL_NO "serial" +#define APP_NVS_KEY_PASSKEY "passkey" + +#define APP_NVS_FULL_KEY_PIEZO "vesiscan/piezo" +#define APP_NVS_FULL_KEY_HW_NO "vesiscan/hw" +#define APP_NVS_FULL_KEY_SERIAL_NO "vesiscan/serial" +#define APP_NVS_FULL_KEY_PASSKEY "vesiscan/passkey" + +static piezo_config_t *m_piezo_cfg; +static app_nvs_piezo_validate_fn m_piezo_validate; +static app_nvs_piezo_log_fn m_piezo_log; + +#if IS_ENABLED(CONFIG_SETTINGS) +static int read_exact(settings_read_cb read_cb, void *cb_arg, + void *dst, size_t expected_len, const char *key) +{ + int rc = read_cb(cb_arg, dst, expected_len); + + if (rc < 0) + { + DBG_ERR("[NVS] %s read failed err=%d\r\n", key, rc); + return rc; + } + if (rc != expected_len) + { + DBG_ERR("[NVS] %s short read (%d)\r\n", key, rc); + return -EINVAL; + } + + return 0; +} + +static int app_nvs_settings_set(const char *name, size_t len, + settings_read_cb read_cb, void *cb_arg) +{ + const char *next; + + if (settings_name_steq(name, APP_NVS_KEY_PIEZO, &next) && (next == NULL)) + { + piezo_config_t loaded; + int err; + + if (len != sizeof(loaded)) + { + DBG_ERR("[NVS] piezo size mismatch (%u)\r\n", (uint32_t)len); + return -EINVAL; + } + + err = read_exact(read_cb, cb_arg, &loaded, sizeof(loaded), APP_NVS_KEY_PIEZO); + if (err) + { + return err; + } + + if ((m_piezo_cfg == NULL) || + ((m_piezo_validate != NULL) && !m_piezo_validate(&loaded))) + { + DBG_ERR("[NVS] piezo invalid, keep defaults\r\n"); + return 0; + } + + *m_piezo_cfg = loaded; + if (m_piezo_log != NULL) + { + m_piezo_log("[NVS] piezo restored", m_piezo_cfg); + } + return 0; + } + + if (settings_name_steq(name, APP_NVS_KEY_HW_NO, &next) && (next == NULL)) + { + if (len != HW_NO_LENGTH) + { + DBG_ERR("[NVS] hw size mismatch (%u)\r\n", (uint32_t)len); + return -EINVAL; + } + + memset(HW_NO, 0, sizeof(HW_NO)); + return read_exact(read_cb, cb_arg, HW_NO, HW_NO_LENGTH, APP_NVS_KEY_HW_NO); + } + + if (settings_name_steq(name, APP_NVS_KEY_SERIAL_NO, &next) && (next == NULL)) + { + if (len != SERIAL_NO_LENGTH) + { + DBG_ERR("[NVS] serial size mismatch (%u)\r\n", (uint32_t)len); + return -EINVAL; + } + + memset(SERIAL_NO, 0, sizeof(SERIAL_NO)); + return read_exact(read_cb, cb_arg, SERIAL_NO, SERIAL_NO_LENGTH, APP_NVS_KEY_SERIAL_NO); + } + + if (settings_name_steq(name, APP_NVS_KEY_PASSKEY, &next) && (next == NULL)) + { + if (len != PASSKEY_LENGTH) + { + DBG_ERR("[NVS] passkey size mismatch (%u)\r\n", (uint32_t)len); + return -EINVAL; + } + + memset(m_static_passkey, 0, sizeof(m_static_passkey)); + return read_exact(read_cb, cb_arg, m_static_passkey, PASSKEY_LENGTH, APP_NVS_KEY_PASSKEY); + } + + return -ENOENT; +} + +SETTINGS_STATIC_HANDLER_DEFINE(app_nvs_settings, + APP_NVS_SETTINGS_NAME, + NULL, + app_nvs_settings_set, + NULL, + NULL); +#endif + +int app_nvs_init(piezo_config_t *piezo_cfg, + app_nvs_piezo_validate_fn piezo_validate, + app_nvs_piezo_log_fn piezo_log) +{ + m_piezo_cfg = piezo_cfg; + m_piezo_validate = piezo_validate; + m_piezo_log = piezo_log; + +#if IS_ENABLED(CONFIG_SETTINGS) + int err = settings_subsys_init(); + + if (err && (err != -EALREADY)) + { + DBG_ERR("[NVS] settings init failed err=%d\r\n", err); + return err; + } + + err = settings_load_subtree(APP_NVS_SETTINGS_NAME); + if (err) + { + DBG_ERR("[NVS] settings load failed err=%d\r\n", err); + return err; + } +#endif + + return 0; +} + +int app_nvs_save_piezo(const piezo_config_t *cfg) +{ +#if IS_ENABLED(CONFIG_SETTINGS) + int err = settings_save_one(APP_NVS_FULL_KEY_PIEZO, cfg, sizeof(*cfg)); + if (err) + { + DBG_ERR("[NVS] piezo save failed err=%d\r\n", err); + } + return err; +#else + ARG_UNUSED(cfg); + return 0; +#endif +} + +int app_nvs_save_hw_no(const char *hw_no) +{ +#if IS_ENABLED(CONFIG_SETTINGS) + int err = settings_save_one(APP_NVS_FULL_KEY_HW_NO, hw_no, HW_NO_LENGTH); + if (err) + { + DBG_ERR("[NVS] hw save failed err=%d\r\n", err); + } + return err; +#else + ARG_UNUSED(hw_no); + return 0; +#endif +} + +int app_nvs_save_serial_no(const char *serial_no) +{ +#if IS_ENABLED(CONFIG_SETTINGS) + int err = settings_save_one(APP_NVS_FULL_KEY_SERIAL_NO, serial_no, SERIAL_NO_LENGTH); + if (err) + { + DBG_ERR("[NVS] serial save failed err=%d\r\n", err); + } + return err; +#else + ARG_UNUSED(serial_no); + return 0; +#endif +} + +int app_nvs_save_passkey(const char *passkey) +{ +#if IS_ENABLED(CONFIG_SETTINGS) + int err = settings_save_one(APP_NVS_FULL_KEY_PASSKEY, passkey, PASSKEY_LENGTH); + if (err) + { + DBG_ERR("[NVS] passkey save failed err=%d\r\n", err); + } + return err; +#else + ARG_UNUSED(passkey); + return 0; +#endif +} diff --git a/src/app_nvs.h b/src/app_nvs.h new file mode 100644 index 0000000..e22267e --- /dev/null +++ b/src/app_nvs.h @@ -0,0 +1,24 @@ +/******************************************************************************* + * @file app_nvs.h + * @brief Application persistent settings stored through Zephyr NVS/settings + ******************************************************************************/ +#ifndef APP_NVS_H__ +#define APP_NVS_H__ + +#include + +#include "parser.h" + +typedef bool (*app_nvs_piezo_validate_fn)(const piezo_config_t *cfg); +typedef void (*app_nvs_piezo_log_fn)(const char *prefix, const piezo_config_t *cfg); + +int app_nvs_init(piezo_config_t *piezo_cfg, + app_nvs_piezo_validate_fn piezo_validate, + app_nvs_piezo_log_fn piezo_log); + +int app_nvs_save_piezo(const piezo_config_t *cfg); +int app_nvs_save_hw_no(const char *hw_no); +int app_nvs_save_serial_no(const char *serial_no); +int app_nvs_save_passkey(const char *passkey); + +#endif /* APP_NVS_H__ */ diff --git a/src/parser.c b/src/parser.c index cbe3f51..3da0e90 100644 --- a/src/parser.c +++ b/src/parser.c @@ -9,14 +9,11 @@ ******************************************************************************/ #include #include -#if IS_ENABLED(CONFIG_SETTINGS) -#include -#endif -#include #include #include #include "parser.h" +#include "app_nvs.h" #include "main.h" #include "debug_print.h" #include "ble_service.h" @@ -45,15 +42,11 @@ #define PIEZO_CFG_DELAY_DEFAULT 10 #define PIEZO_CFG_SAMPLES_DEFAULT 100 #define PIEZO_CFG_AVG_DEFAULT 10 -#define PIEZO_CFG_AVG_MAX 100 -#define PIEZO_CFG_DELAY_MAX_US 1000 +#define PIEZO_CFG_AVG_MAX 20 +#define PIEZO_CFG_DELAY_MAX_US 100 #define PIEZO_POST_SELECT_SETTLE_US 500 #define PIEZO_AVG_INTER_BURST_GAP_US 500 -#define PIEZO_SETTINGS_NAME "vesiscan" -#define PIEZO_SETTINGS_CFG_KEY "piezo" -#define PIEZO_SETTINGS_FULL_KEY "vesiscan/piezo" - static uint16_t piezo_channels[PIEZO_NUM_CHANNELS][ECHO_ADC_MAX_SAMPLES]; static uint16_t echo_capture[ECHO_ADC_MAX_SAMPLES]; static uint32_t echo_accum[ECHO_ADC_MAX_SAMPLES]; @@ -73,27 +66,33 @@ static piezo_config_t g_piezo_config = { static bool piezo_config_validate(const piezo_config_t *cfg) { - if (cfg == NULL) { + if (cfg == NULL) + { return false; } - if (cfg->freq != PIEZO_CFG_FREQ_DEFAULT) { + if (cfg->freq != PIEZO_CFG_FREQ_DEFAULT) + { return false; } - if ((cfg->cycles < 3U) || (cfg->cycles > 7U)) { + if ((cfg->cycles < 3U) || (cfg->cycles > 7U)) + { return false; } - if ((cfg->avg == 0U) || (cfg->avg > PIEZO_CFG_AVG_MAX)) { + if ((cfg->avg == 0U) || (cfg->avg > PIEZO_CFG_AVG_MAX)) + { return false; } - if (cfg->delay_us > PIEZO_CFG_DELAY_MAX_US) { + if (cfg->delay_us > PIEZO_CFG_DELAY_MAX_US) + { return false; } - if ((cfg->samples == 0U) || (cfg->samples > ECHO_ADC_MAX_SAMPLES)) { + if ((cfg->samples == 0U) || (cfg->samples > ECHO_ADC_MAX_SAMPLES)) + { return false; } @@ -116,88 +115,18 @@ const piezo_config_t *piezo_config_get(void) return &g_piezo_config; } -#if IS_ENABLED(CONFIG_SETTINGS) -static int piezo_settings_set(const char *name, size_t len, - settings_read_cb read_cb, void *cb_arg) -{ - const char *next; - int rc; - - if (settings_name_steq(name, PIEZO_SETTINGS_CFG_KEY, &next) && (next == NULL)) - { - piezo_config_t loaded; - - if (len != sizeof(loaded)) { - DBG_ERR("[CFG] piezo settings size mismatch (%u)\r\n", (uint32_t)len); - return -EINVAL; - } - - rc = read_cb(cb_arg, &loaded, sizeof(loaded)); - if (rc < 0) { - DBG_ERR("[CFG] piezo settings read failed err=%d\r\n", rc); - return rc; - } - if (rc != sizeof(loaded)) { - DBG_ERR("[CFG] piezo settings short read (%d)\r\n", rc); - return -EINVAL; - } - - if (!piezo_config_validate(&loaded)) { - DBG_ERR("[CFG] piezo settings invalid, keep defaults\r\n"); - return 0; - } - - g_piezo_config = loaded; - piezo_config_log("[CFG] piezo restored", &g_piezo_config); - return 0; - } - - return -ENOENT; -} - -SETTINGS_STATIC_HANDLER_DEFINE(piezo_settings, - PIEZO_SETTINGS_NAME, - NULL, - piezo_settings_set, - NULL, - NULL); -#endif - int piezo_config_init(void) { -#if IS_ENABLED(CONFIG_SETTINGS) - int err = settings_subsys_init(); - if (err && (err != -EALREADY)) { - DBG_ERR("[CFG] settings init failed err=%d\r\n", err); + int err = app_nvs_init(&g_piezo_config, piezo_config_validate, piezo_config_log); + if (err) + { return err; } - err = settings_load_subtree(PIEZO_SETTINGS_NAME); - if (err) { - DBG_ERR("[CFG] piezo settings load failed err=%d\r\n", err); - return err; - } -#endif - piezo_config_log("[CFG] piezo active", &g_piezo_config); return 0; } -static int piezo_config_save(void) -{ -#if IS_ENABLED(CONFIG_SETTINGS) - int err = settings_save_one(PIEZO_SETTINGS_FULL_KEY, - &g_piezo_config, - sizeof(g_piezo_config)); - if (err) { - DBG_ERR("[CFG] piezo settings save failed err=%d\r\n", err); - } - return err; -#else - return 0; -#endif -} - /*============================================================================== * CRC16 (CRC-CCITT, Nordic SDK 호환) *============================================================================*/ @@ -221,7 +150,8 @@ static bool get_data_u16_be(const uint8_t *data, uint8_t data_len, { uint8_t offset = (uint8_t)(word_index * 2U); - if ((offset + 1U) >= data_len) { + if ((offset + 1U) >= data_len) + { return false; } @@ -229,10 +159,10 @@ static bool get_data_u16_be(const uint8_t *data, uint8_t data_len, return true; } -static void copy_fixed_ascii(char *dst, size_t dst_len, - const char *src, size_t src_len) +static void copy_fixed_ascii(char *dst, size_t dst_len, const char *src, size_t src_len) { - if (src_len > dst_len) { + if (src_len > dst_len) + { src_len = dst_len; } @@ -242,7 +172,8 @@ static void copy_fixed_ascii(char *dst, size_t dst_len, static char ascii_to_lower(char ch) { - if ((ch >= 'A') && (ch <= 'Z')) { + if ((ch >= 'A') && (ch <= 'Z')) + { return (char)(ch - 'A' + 'a'); } @@ -321,11 +252,12 @@ static int send_response_imu(const int16_t accel[3], const int16_t gyro[3]) buf[0] = 'r'; buf[1] = 's'; buf[2] = 'p'; buf[3] = ':'; - const int16_t vals[6] = { + const int16_t vals[6] ={ accel[0], accel[1], accel[2], gyro[0], gyro[1], gyro[2] }; - for (int i = 0; i < 6; i++) { + for (int i = 0; i < 6; i++) + { buf[4 + i * 2] = (uint8_t)((uint16_t)vals[i] >> 8); /* MSB */ buf[4 + i * 2 + 1] = (uint8_t)((uint16_t)vals[i] & 0xFF); /* LSB */ } @@ -396,7 +328,8 @@ static void send_response_bundle(uint16_t batt_mv, ble_data_send(buf, sizeof(tx_bundle_buf)); } -static void send_response_piezo_config(uint16_t freq, +static void send_response_piezo_config(const char *tag, + uint16_t freq, uint16_t cycles, uint16_t avg, uint16_t delay_us, @@ -404,7 +337,10 @@ static void send_response_piezo_config(uint16_t freq, { uint8_t *buf = tx_cfg_buf; - buf[0] = 'r'; buf[1] = 'c'; buf[2] = 'f'; buf[3] = ':'; + buf[0] = tag[0]; + buf[1] = tag[1]; + buf[2] = tag[2]; + buf[3] = tag[3]; buf[4] = (uint8_t)(freq >> 8); buf[5] = (uint8_t)(freq & 0xFF); buf[6] = (uint8_t)(cycles >> 8); @@ -460,7 +396,8 @@ static int perform_piezo_sweep(void) const piezo_config_t *cfg = piezo_config_get(); uint16_t capture_delay_us = cfg->delay_us; - if (capture_delay_us < PIEZO_BURST_TO_ADC_DELAY_US) { + if (capture_delay_us < PIEZO_BURST_TO_ADC_DELAY_US) + { capture_delay_us = PIEZO_BURST_TO_ADC_DELAY_US; } @@ -527,27 +464,32 @@ static int perform_single_piezo_capture(uint8_t cycles, uint16_t averaging, uint8_t channel) { - if (channel >= PIEZO_NUM_CHANNELS) { + if (channel >= PIEZO_NUM_CHANNELS) + { return ECHO_STATUS_MUX; } - if ((num_samples == 0U) || (num_samples > ECHO_ADC_MAX_SAMPLES)) { + if ((num_samples == 0U) || (num_samples > ECHO_ADC_MAX_SAMPLES)) + { return ECHO_STATUS_CAPTURE; } - if (averaging == 0U) { + if (averaging == 0U) + { averaging = 1U; } int err = piezo_select_channel(channel); - if (err) { + if (err) + { return ECHO_STATUS_MUX; } k_busy_wait(PIEZO_POST_SELECT_SETTLE_US); err = echo_adc_wake(); - if (err) { + if (err) + { return ECHO_STATUS_CAPTURE; } @@ -555,7 +497,8 @@ static int perform_single_piezo_capture(uint8_t cycles, for (uint16_t avg = 0; avg < averaging; avg++) { - if (avg > 0U) { + if (avg > 0U) + { k_busy_wait(PIEZO_AVG_INTER_BURST_GAP_US); } @@ -563,7 +506,8 @@ static int perform_single_piezo_capture(uint8_t cycles, k_busy_wait(delay_us); err = echo_adc_capture(echo_capture, num_samples); - if (err) { + if (err) + { return ECHO_STATUS_CAPTURE; } @@ -612,7 +556,8 @@ static int cmd_msp(const uint8_t *data, uint8_t data_len) int16_t accel[3], gyro[3]; int ret = imu_read(accel, gyro); - if (ret != 0) { + if (ret != 0) + { send_response_u16("rsp:", 0xFFFF); DBG_PRINTF("[CMD] msp: FAIL (imu_read ret=%d) -> rsp: 0xFFFF\r\n", ret); return 1; @@ -667,9 +612,7 @@ static int cmd_mst(const uint8_t *data, uint8_t data_len) /* 음수 온도도 2's complement로 그대로 전송 (앱이 int16로 해석) */ send_response_u16("rso:", (uint16_t)t_cdeg); - DBG_PRINTF("[CMD] mst -> %d.%02d C\r\n", - t_cdeg / 100, - (t_cdeg < 0 ? -t_cdeg : t_cdeg) % 100); + DBG_PRINTF("[CMD] mst -> %d.%02d C\r\n", t_cdeg / 100, (t_cdeg < 0 ? -t_cdeg : t_cdeg) % 100); return 1; } @@ -683,7 +626,8 @@ static int cmd_mpa(const uint8_t *data, uint8_t data_len) ARG_UNUSED(data_len); DBG_CORE("[MPA] enter\r\n"); - if (piezo_init() != 0) { + if (piezo_init() != 0) + { DBG_ERR("[MPA] piezo_init failed\r\n"); send_response_u16("rpa:", 0); return 1; @@ -704,7 +648,8 @@ static int cmd_mpb(const uint8_t *data, uint8_t data_len) /* mpb?: piezo TX/RX 전원 레일을 끈다. */ DBG_CORE("[MPB] enter\r\n"); - if (piezo_init() != 0) { + if (piezo_init() != 0) + { DBG_ERR("[MPB] piezo_init failed\r\n"); send_response_u16("rpb:", 0); return 1; @@ -744,7 +689,8 @@ static int cmd_mpc(const uint8_t *data, uint8_t data_len) power_button_suspend(true); - if (piezo_init() != 0) { + if (piezo_init() != 0) + { power_button_suspend(false); send_response_u16("rpc:", 0); return 1; @@ -752,7 +698,8 @@ static int cmd_mpc(const uint8_t *data, uint8_t data_len) piezo_power_on(); - if (piezo_select_channel((uint8_t)(piezo_ch % PIEZO_NUM_CHANNELS)) != 0) { + if (piezo_select_channel((uint8_t)(piezo_ch % PIEZO_NUM_CHANNELS)) != 0) + { piezo_power_off(); power_button_suspend(false); send_response_u16("rpc:", 0); @@ -794,13 +741,16 @@ static int cmd_mec(const uint8_t *data, uint8_t data_len) * 테스트용 * mec?: 단일 채널 burst + echo capture */ - if (num_samples > ECHO_ADC_MAX_SAMPLES) { + if (num_samples > ECHO_ADC_MAX_SAMPLES) + { num_samples = ECHO_ADC_MAX_SAMPLES; } - if ((cycles < 3U) || (cycles > 7U)) { + if ((cycles < 3U) || (cycles > 7U)) + { cycles = PIEZO_SW_BURST_CYCLES; } - if (averaging == 0U) { + if (averaging == 0U) + { averaging = 1U; } @@ -810,11 +760,7 @@ static int cmd_mec(const uint8_t *data, uint8_t data_len) int status = start_piezo_session(); if (status == ECHO_STATUS_OK) { - status = perform_single_piezo_capture((uint8_t)cycles, - delay_us, - num_samples, - averaging, - (uint8_t)(piezo_ch % PIEZO_NUM_CHANNELS)); + status = perform_single_piezo_capture((uint8_t)cycles, delay_us, num_samples, averaging, (uint8_t)(piezo_ch % PIEZO_NUM_CHANNELS)); } if (status == ECHO_STATUS_OK) @@ -970,7 +916,7 @@ static int cmd_mcf(const uint8_t *data, uint8_t data_len) ARG_UNUSED(data_len); const piezo_config_t *cfg = piezo_config_get(); - send_response_piezo_config(cfg->freq, cfg->cycles, cfg->avg, cfg->delay_us, cfg->samples); + send_response_piezo_config("rcf:", cfg->freq, cfg->cycles, cfg->avg, cfg->delay_us, cfg->samples); piezo_config_log("[CMD] mcf ->", cfg); return 1; } @@ -984,7 +930,7 @@ static int cmd_mcs(const uint8_t *data, uint8_t data_len) if (data_len < 10U) { - send_response_u16("rcs:", 0xFFFF); + send_response_piezo_config("rcs:", 0xFFFF, 0U, 0U, 0U, 0U); DBG_PRINTF("[CMD] mcs: insufficient data len=%u\r\n", data_len); return 1; } @@ -997,7 +943,7 @@ static int cmd_mcs(const uint8_t *data, uint8_t data_len) if (!piezo_config_validate(&cfg)) { - send_response_u16("rcs:", 0xFFFE); + send_response_piezo_config("rcs:", 0xFFFF, cfg.cycles, cfg.avg, cfg.delay_us, cfg.samples); piezo_config_log("[CMD] mcs invalid", &cfg); return 1; } @@ -1049,6 +995,13 @@ static int cmd_mwh(const uint8_t *data, uint8_t data_len) memset(HW_NO, 0, sizeof(HW_NO)); memcpy(HW_NO, data, HW_NO_LENGTH); + int err = app_nvs_save_hw_no(HW_NO); + if (err) + { + send_response_u16("rwh:", 0xFFFD); + return 1; + } + send_response_ascii("rwh:", HW_NO, HW_NO_LENGTH); DBG_PRINTF("[CMD] mwh updated\r\n"); return 1; @@ -1062,7 +1015,8 @@ static int cmd_mrh(const uint8_t *data, uint8_t data_len) ARG_UNUSED(data_len); err = send_response_ascii("rrh:", HW_NO, HW_NO_LENGTH); - if (err) { + if (err) + { DBG_ERR("[CMD] mrh tx failed err=%d\r\n", err); } DBG_PRINTF("[CMD] mrh read\r\n"); @@ -1080,6 +1034,13 @@ static int cmd_mws(const uint8_t *data, uint8_t data_len) memset(SERIAL_NO, 0, sizeof(SERIAL_NO)); memcpy(SERIAL_NO, data, SERIAL_NO_LENGTH); + int err = app_nvs_save_serial_no(SERIAL_NO); + if (err) + { + send_response_u16("rws:", 0xFFFD); + return 1; + } + send_response_ascii("rws:", SERIAL_NO, SERIAL_NO_LENGTH); DBG_PRINTF("[CMD] mws updated\r\n"); return 1; @@ -1093,7 +1054,8 @@ static int cmd_mrs(const uint8_t *data, uint8_t data_len) ARG_UNUSED(data_len); err = send_response_ascii("rrs:", SERIAL_NO, SERIAL_NO_LENGTH); - if (err) { + if (err) + { DBG_ERR("[CMD] mrs tx failed err=%d\r\n", err); } DBG_PRINTF("[CMD] mrs read\r\n"); @@ -1111,6 +1073,13 @@ static int cmd_mpz(const uint8_t *data, uint8_t data_len) memset(m_static_passkey, 0, sizeof(m_static_passkey)); memcpy(m_static_passkey, data, PASSKEY_LENGTH); + int err = app_nvs_save_passkey(m_static_passkey); + if (err) + { + send_response_u16("rpz:", 0xFFFD); + return 1; + } + send_response_ascii("rpz:", m_static_passkey, PASSKEY_LENGTH); DBG_PRINTF("[CMD] mpz updated\r\n"); return 1; @@ -1206,18 +1175,14 @@ int dr_parser(const uint8_t *buf, uint16_t len) /* CRC16 검증 (6바이트 이상이면 마지막 2바이트가 CRC) */ if (len >= 6) { - /* - * 이 프로토콜은 끝 2바이트에 CRC16이 붙는다. - * 값이 다르면 "명령 이름은 맞아 보여도 데이터가 깨졌다"는 뜻이므로 바로 버린다. - */ uint16_t calc_crc = dr_crc16_compute(buf, len - 2); uint16_t recv_crc = (uint16_t)(buf[len - 2]) | ((uint16_t)(buf[len - 1]) << 8); if (calc_crc != recv_crc) { - DBG_ERR("[CMD] CRC fail tag=%s calc=0x%04X recv=0x%04X\r\n", - raw_tag, calc_crc, recv_crc); - if (send_response_tag_echo("rxc:", raw_tag) != 0) { + DBG_ERR("[CMD] CRC fail tag=%s calc=0x%04X recv=0x%04X\r\n", raw_tag, calc_crc, recv_crc); + if (send_response_tag_echo("rxc:", raw_tag) != 0) + { DBG_ERR("[CMD] rxc tx failed\r\n"); } return -1;