319 lines
10 KiB
C
319 lines
10 KiB
C
/*******************************************************************************
|
|
* @file cmd_parse.c
|
|
* @brief Command Parser Wrapper (Legacy Compatibility)
|
|
* @author Charles KWON <charleskwon@medithings.co.kr>
|
|
* @date 2025-02-04
|
|
* @copyright (c) 2025 Medithings Inc. All rights reserved.
|
|
*
|
|
* @details This file provides:
|
|
* - Legacy compatibility wrapper (received_command_process)
|
|
* - Utility functions (error handling, validation)
|
|
* - EEPROM read functions
|
|
*
|
|
* Actual parsing is handled by mt_parser/parser.c
|
|
* Command handlers are in cmd/cmd.c
|
|
******************************************************************************/
|
|
|
|
#include "cmd_parse.h"
|
|
#include "debug_print.h"
|
|
#include "parser.h"
|
|
#include "i2c_manager.h"
|
|
#include "app_timer.h"
|
|
#include "config/device_config.h"
|
|
#include "ble/ble_data_tx.h"
|
|
#include "ble_nus.h"
|
|
#include "crc16.h"
|
|
#include "cat_interface.h"
|
|
#include "storage/dr_mem.h"
|
|
#include <stdarg.h>
|
|
#include <string.h>
|
|
|
|
/*==============================================================================
|
|
* @section DEFINES Constants
|
|
*============================================================================*/
|
|
|
|
#define err_code1 65535 /* length error */
|
|
#define err_code2 65534 /* activate error */
|
|
#define err_code3 65533 /* param error */
|
|
#define err_code4 65532 /* ? missing */
|
|
#define err_code5 65531 /* CMD wrong */
|
|
#define err_code6 65530 /* CRC wrong */
|
|
|
|
/*==============================================================================
|
|
* @section EXTERN External Declarations
|
|
*============================================================================*/
|
|
|
|
extern uint8_t m_reset_status;
|
|
|
|
/* Note: SERIAL_NO, bond_data_delete, m_static_passkey, m_pd_adc_cnt,
|
|
m_pd_delay_us, m_life_cycle are declared in device_config.h */
|
|
|
|
/* Defined in measurements.h */
|
|
extern uint16_t led_pd_dac_v[];
|
|
|
|
/* Defined in main.c */
|
|
extern char ble_tx_buffer[];
|
|
extern volatile bool processing;
|
|
extern bool ble_got_new_data;
|
|
|
|
/* BLE buffer (defined in ble_data_tx.c) */
|
|
extern uint8_t ble_bin_buffer[];
|
|
|
|
/* Parser globals (defined in parser.c) */
|
|
extern dr_platform_if_t g_plat;
|
|
extern bool g_log_enable;
|
|
|
|
/*==============================================================================
|
|
* @section GLOBALS Global Variables (used by other modules)
|
|
*============================================================================*/
|
|
|
|
uint8_t resetCount = 0; /**< Reset counter */
|
|
bool info4 = false; /**< Additional info flag for PD Full mode */
|
|
|
|
/*==============================================================================
|
|
* @section STATIC Static Variables
|
|
*============================================================================*/
|
|
|
|
static uint32_t processing_start_tick = 0;
|
|
|
|
/*==============================================================================
|
|
* @section UTIL Utility Functions
|
|
*============================================================================*/
|
|
|
|
/**
|
|
* @brief Internal log function for parser
|
|
*/
|
|
static void log_printf(const char *fmt, ...)
|
|
{
|
|
va_list args;
|
|
va_start(args, fmt);
|
|
vprintf(fmt, args);
|
|
va_end(args);
|
|
}
|
|
|
|
/*==============================================================================
|
|
* @section CRC CRC Functions
|
|
*============================================================================*/
|
|
|
|
bool crc16_check(uint8_t const *p_data, uint32_t data_len, uint16_t expected_crc)
|
|
{
|
|
uint16_t computed_crc = crc16_compute(p_data, data_len, NULL);
|
|
return (computed_crc == expected_crc);
|
|
}
|
|
|
|
bool crc16_check_packet(uint8_t const *packet, uint32_t packet_len)
|
|
{
|
|
if (packet_len < 2) return false;
|
|
|
|
uint32_t data_len = packet_len - 2;
|
|
uint16_t expected_crc = (packet[packet_len - 1] << 8) | packet[packet_len - 2];
|
|
|
|
return crc16_check(packet, data_len, expected_crc);
|
|
}
|
|
|
|
/*==============================================================================
|
|
* @section ERROR Error Handling Functions
|
|
*============================================================================*/
|
|
|
|
bool length_error(const char *cmd, uint8_t target_length, uint8_t length)
|
|
{
|
|
if (target_length == length) {
|
|
return true;
|
|
}
|
|
|
|
char resp_error[4];
|
|
resp_error[0] = 'r';
|
|
resp_error[1] = cmd[1];
|
|
resp_error[2] = cmd[2];
|
|
resp_error[3] = '!';
|
|
|
|
single_format_data(ble_bin_buffer, resp_error, err_code1);
|
|
binary_tx_handler(ble_bin_buffer, 3);
|
|
return false;
|
|
}
|
|
|
|
bool activate_error(const char *cmd, bool device_status)
|
|
{
|
|
if (device_status == true) {
|
|
return true;
|
|
}
|
|
|
|
char resp_error[4];
|
|
resp_error[0] = 'r';
|
|
resp_error[1] = cmd[1];
|
|
resp_error[2] = cmd[2];
|
|
resp_error[3] = '!';
|
|
|
|
single_format_data(ble_bin_buffer, resp_error, err_code2);
|
|
binary_tx_handler(ble_bin_buffer, 3);
|
|
return false;
|
|
}
|
|
|
|
void param_error(const char *cmd)
|
|
{
|
|
char resp_error[4];
|
|
resp_error[0] = 'r';
|
|
resp_error[1] = cmd[1];
|
|
resp_error[2] = cmd[2];
|
|
resp_error[3] = '!';
|
|
|
|
single_format_data(ble_bin_buffer, resp_error, err_code3);
|
|
binary_tx_handler(ble_bin_buffer, 3);
|
|
}
|
|
|
|
void quest_error(const char *cmd)
|
|
{
|
|
char resp_error[4];
|
|
const char pass_init[6] = "123456";
|
|
|
|
if ((cmd[0] == '*') && (cmd[1] == '*') && (cmd[2] == '*') && (cmd[3] == '*')) {
|
|
if (dr_memWrite("passkey", (uint8_t *)pass_init, 6) != NRF_SUCCESS) {
|
|
DBG_PRINTF("ERR!!! passkey write fail\r\n\r\n");
|
|
}
|
|
|
|
resp_error[0] = '*';
|
|
resp_error[1] = cmd[1];
|
|
resp_error[2] = cmd[2];
|
|
resp_error[3] = '*';
|
|
single_format_data(ble_bin_buffer, resp_error, err_code4);
|
|
binary_tx_handler(ble_bin_buffer, 3);
|
|
} else {
|
|
resp_error[0] = 'r';
|
|
resp_error[1] = cmd[1];
|
|
resp_error[2] = cmd[2];
|
|
resp_error[3] = '!';
|
|
|
|
single_format_data(ble_bin_buffer, resp_error, err_code4);
|
|
binary_tx_handler(ble_bin_buffer, 3);
|
|
}
|
|
}
|
|
|
|
/*==============================================================================
|
|
* @section INIT_READ Initial Values Read (via dr_mem API)
|
|
*============================================================================*/
|
|
|
|
ret_code_t eeprom_init_values_read(void)
|
|
{
|
|
ret_code_t err_code;
|
|
|
|
/* FDS entries: Serial Number (12B, AES) */
|
|
err_code = dr_memRead("serial_no", (uint8_t *)SERIAL_NO, 12);
|
|
if (err_code != NRF_SUCCESS) return err_code;
|
|
DBG_PRINTF("\r\n SN:%s \r\n", SERIAL_NO);
|
|
|
|
/* FDS entries: Passkey (6B, AES) */
|
|
err_code = dr_memRead("passkey", (uint8_t *)m_static_passkey, 6);
|
|
if (err_code != NRF_SUCCESS) return err_code;
|
|
DBG_PRINTF("\r\n passkey-0 :%s \n", m_static_passkey);
|
|
|
|
/* FDS entries: Bond data delete (1B) */
|
|
{
|
|
uint8_t raw = 0;
|
|
err_code = dr_memRead("bond_delete", &raw, 1);
|
|
if (err_code != NRF_SUCCESS) return err_code;
|
|
bond_data_delete = (raw != 0);
|
|
}
|
|
DBG_PRINTF("\r\n bond_data_delete :%d \n", bond_data_delete);
|
|
|
|
/* FDS entries: Reset status (1B) */
|
|
err_code = dr_memRead("reset_status", &m_reset_status, 1);
|
|
if (err_code != NRF_SUCCESS) return err_code;
|
|
|
|
/* FDS entries: PD ADC count (1B) */
|
|
err_code = dr_memRead("pd_adc_cnt", &m_pd_adc_cnt, 1);
|
|
if (err_code != NRF_SUCCESS) return err_code;
|
|
if (m_pd_adc_cnt == 0 || m_pd_adc_cnt >= 255) {
|
|
m_pd_adc_cnt = 8;
|
|
}
|
|
|
|
/* FDS entries: PD delay (2B) */
|
|
err_code = dr_memRead("pd_delay", &m_pd_delay_us, 2);
|
|
if (err_code != NRF_SUCCESS) return err_code;
|
|
if (m_pd_delay_us < 5000 || m_pd_delay_us > 30000) {
|
|
m_pd_delay_us = 8000;
|
|
}
|
|
|
|
/* W25Q32 entries: AGC Gain array (96B) */
|
|
err_code = dr_memRead("agc_gain", led_pd_dac_v, 96);
|
|
if (err_code != NRF_SUCCESS) return err_code;
|
|
|
|
/* W25Q32 entries: Life cycle (4B) */
|
|
err_code = dr_memRead("life_cycle", &m_life_cycle, 4);
|
|
if (err_code != NRF_SUCCESS) return err_code;
|
|
|
|
DBG_PRINTF("\r\n m_life_cycle:%u, m_pd_delay_us:%u, m_pd_adc_cnt:%u \r\n",
|
|
m_life_cycle, m_pd_delay_us, m_pd_adc_cnt);
|
|
|
|
return NRF_SUCCESS;
|
|
}
|
|
|
|
/*==============================================================================
|
|
* @section API Main Entry Point
|
|
*============================================================================*/
|
|
|
|
/**
|
|
* @brief Process received command from UART or BLE
|
|
* @details Initializes parser on first call, then delegates to dr_cmd_parser
|
|
*/
|
|
void received_command_process(uint8_t const *data_array, which_cmd_t cmd_t, uint8_t length)
|
|
{
|
|
uint8_t r_data[BLE_NUS_MAX_DATA_LEN] = {0};
|
|
int parser_result;
|
|
|
|
(void)cmd_t; /* Currently not used by new parser */
|
|
|
|
ble_got_new_data = true;
|
|
memset(ble_tx_buffer, 0, BLE_NUS_MAX_DATA_LEN);
|
|
|
|
/* Copy data to local buffer */
|
|
for (uint16_t i = 0; i < length; i++) {
|
|
r_data[i] = data_array[i];
|
|
}
|
|
|
|
DBG_PRINTF("data : %s\r\n", r_data);
|
|
DBG_PRINTF("Length : %d\r\n", length);
|
|
|
|
/* Initialize parser (once) */
|
|
static bool parser_initialized = false;
|
|
|
|
if (!parser_initialized) {
|
|
g_plat.log = log_printf;
|
|
g_plat.tx_bin = binary_tx_handler;
|
|
g_plat.crc_check = true; /* CRC enabled */
|
|
g_log_enable = true;
|
|
|
|
parser_initialized = true;
|
|
DBG_PRINTF(">>> Parser initialized (mt_parser)\r\n");
|
|
}
|
|
|
|
/* Check if already processing */
|
|
if (processing == true) {
|
|
uint32_t now = app_timer_cnt_get();
|
|
|
|
if (processing_start_tick == 0) {
|
|
processing_start_tick = now;
|
|
}
|
|
|
|
/* Timeout check (5 seconds) */
|
|
if (app_timer_cnt_diff_compute(now, processing_start_tick) > APP_TIMER_TICKS(5000)) {
|
|
processing = false;
|
|
processing_start_tick = 0;
|
|
DBG_PRINTF("processing timeout -> force reset to false\r\n");
|
|
} else {
|
|
DBG_PRINTF("Busy - command ignored\r\n");
|
|
return;
|
|
}
|
|
}
|
|
|
|
/* Call mt_parser */
|
|
parser_result = dr_cmd_parser(r_data, length);
|
|
|
|
if (parser_result > 0) {
|
|
DBG_PRINTF(">>> Handled by mt_parser (result=%d)\r\n", parser_result);
|
|
} else if (parser_result == 9) {
|
|
DBG_PRINTF(">>> CRC/Parse error\r\n");
|
|
} else {
|
|
DBG_PRINTF(">>> Unknown command\r\n");
|
|
}
|
|
}
|