/**
 * @file    icp67_decode.c
 * @brief   ICP67 帧解码 — 16 种 TI 消息类型解码 + 文件/ZIP 子命令分发
 * @details 本文件是 ICP67 协议栈的"协议解释器"，负责将原始帧字节解析为回调调用。
 *
 *          架构设计:
 *          ┌─────────────────────────────────────────────┐
 *          │ icp67_decode()  顶层分发 (查 TI 映射表)      │
 *          │   ├─ icp67_decode_ti_1  读独立编码参数响应   │
 *          │   ├─ icp67_decode_ti_2  写独立编码参数响应   │
 *          │   ├─ icp67_decode_ti_3  读组合编码参数(分帧) │
 *          │   ├─ icp67_decode_ti_4  (空桩)              │
 *          │   ├─ icp67_decode_ti_5  对时响应            │
 *          │   ├─ icp67_decode_ti_6  自检响应            │
 *          │   ├─ icp67_decode_ti_9  升级响应            │
 *          │   ├─ icp67_decode_ti_11 文件操作(子命令分发) │
 *          │   │    ├─ ti_11_2  读目录响应               │
 *          │   │    ├─ ti_11_4  读文件激活响应           │
 *          │   │    ├─ ti_11_5  读文件内容               │
 *          │   │    ├─ ti_11_8  写文件激活响应           │
 *          │   │    └─ ti_11_10 写文件内容响应           │
 *          │   ├─ icp67_decode_ti_30 ZIP波形(子命令分发) │
 *          │   │    ├─ ti_30_1  录波目录                │
 *          │   │    └─ ti_30_3  压缩文件内容            │
 *          │   ├─ icp67_decode_ti_200  遥测传输          │
 *          │   ├─ icp67_decode_ti_201  遥信传输          │
 *          │   ├─ icp67_decode_ti_202  计量传输          │
 *          │   ├─ icp67_decode_ti_203  (空桩)            │
 *          │   ├─ icp67_decode_ti_204  SOE 事件传输      │
 *          │   ├─ icp67_decode_ti_205  故障事件传输      │
 *          │   └─ icp67_decode_ti_207  遥测扰动传输      │
 *          └─────────────────────────────────────────────┘
 *
 *          关键设计:
 *          - C 数组查表替代 C++ std::map，无动态内存分配
 *          - 所有解码函数通过 p_icp67->method.xxx_cb 回调 (实例化)
 *          - TI_205 使用固定大小数组暂存 ST/MX 数据，避免 std::vector
 *          - 每个解码函数负责参数校验、COT 验证、rtx_flag 管理
 */

#include "icp67.h"
#include "myLog.h"
#include <string.h>

#define MAX_FAULT_ST_INFO 64
#define MAX_FAULT_MX_INFO 64
#define MAX_ZIP_FILE_INFO 32

/* =========================== TI 解码函数前向声明 =========================== */

static int icp67_decode_ti_1(stru_icp67 *p_icp67, uint8_t *p_rx, uint16_t rx_len);
static int icp67_decode_ti_2(stru_icp67 *p_icp67, uint8_t *p_rx, uint16_t rx_len);
static int icp67_decode_ti_3(stru_icp67 *p_icp67, uint8_t *p_rx, uint16_t rx_len);
static int icp67_decode_ti_4(stru_icp67 *p_icp67, uint8_t *p_rx, uint16_t rx_len);
static int icp67_decode_ti_5(stru_icp67 *p_icp67, uint8_t *p_rx, uint16_t rx_len);
static int icp67_decode_ti_6(stru_icp67 *p_icp67, uint8_t *p_rx, uint16_t rx_len);
static int icp67_decode_ti_9(stru_icp67 *p_icp67, uint8_t *p_rx, uint16_t rx_len);
static int icp67_decode_ti_11(stru_icp67 *p_icp67, uint8_t *p_rx, uint16_t rx_len);
static int icp67_decode_ti_30(stru_icp67 *p_icp67, uint8_t *p_rx, uint16_t rx_len);
static int icp67_decode_ti_200(stru_icp67 *p_icp67, uint8_t *p_rx, uint16_t rx_len);
static int icp67_decode_ti_201(stru_icp67 *p_icp67, uint8_t *p_rx, uint16_t rx_len);
static int icp67_decode_ti_202(stru_icp67 *p_icp67, uint8_t *p_rx, uint16_t rx_len);
static int icp67_decode_ti_203(stru_icp67 *p_icp67, uint8_t *p_rx, uint16_t rx_len);
static int icp67_decode_ti_204(stru_icp67 *p_icp67, uint8_t *p_rx, uint16_t rx_len);
static int icp67_decode_ti_205(stru_icp67 *p_icp67, uint8_t *p_rx, uint16_t rx_len);
static int icp67_decode_ti_207(stru_icp67 *p_icp67, uint8_t *p_rx, uint16_t rx_len);

/* TI_11 文件操作子命令解码 */
static int icp67_decode_ti_11_2(stru_icp67 *p_icp67, uint8_t *p_rx, uint16_t rx_len);
static int icp67_decode_ti_11_4(stru_icp67 *p_icp67, uint8_t *p_rx, uint16_t rx_len);
static int icp67_decode_ti_11_5(stru_icp67 *p_icp67, uint8_t *p_rx, uint16_t rx_len);
static int icp67_decode_ti_11_8(stru_icp67 *p_icp67, uint8_t *p_rx, uint16_t rx_len);
static int icp67_decode_ti_11_10(stru_icp67 *p_icp67, uint8_t *p_rx, uint16_t rx_len);

/* TI_30 录波文件子命令解码 */
static int icp67_decode_ti_30_1(stru_icp67 *p_icp67, uint8_t *p_rx, uint16_t rx_len);
static int icp67_decode_ti_30_3(stru_icp67 *p_icp67, uint8_t *p_rx, uint16_t rx_len);

/* =========================== 解码映射表 =========================== */
/*
 * 用 C 数组实现 TI→解码函数 映射，替代原 C++ 的 std::map。
 *
 * 为什么用数组而不是 switch:
 *   - switch 无法动态扩展，新增 TI 需要修改核心分发函数
 *   - 数组查表只需 O(n) 遍历 (n=16)，n 很小性能无差异
 *   - 每个表项包含 {ti, func} 配对，新增 TI 仅需追加条目
 *
 * 查表函数 (ti_decode_find/file_decode_find/zip_decode_find):
 *   - 遍历数组，匹配 cmd/ti → 返回函数指针
 *   - 未找到返回 NULL (由调用者处理)
 */

typedef struct
{
	uint8_t         ti;
	icp67_decode_cb func;
}stru_ti_decode_entry;

static stru_ti_decode_entry g_ti_decode_table[] =
{
	{TI_1,   icp67_decode_ti_1},
	{TI_2,   icp67_decode_ti_2},
	{TI_3,   icp67_decode_ti_3},
	{TI_4,   icp67_decode_ti_4},
	{TI_5,   icp67_decode_ti_5},
	{TI_6,   icp67_decode_ti_6},
	{TI_9,   icp67_decode_ti_9},
	{TI_11,  icp67_decode_ti_11},
	{TI_30,  icp67_decode_ti_30},
	{TI_200, icp67_decode_ti_200},
	{TI_201, icp67_decode_ti_201},
	{TI_202, icp67_decode_ti_202},
	{TI_203, icp67_decode_ti_203},
	{TI_204, icp67_decode_ti_204},
	{TI_205, icp67_decode_ti_205},
	{TI_207, icp67_decode_ti_207},
};

#define TI_DECODE_TABLE_SIZE (sizeof(g_ti_decode_table) / sizeof(g_ti_decode_table[0]))

static stru_ti_decode_entry g_file_decode_table[] =
{
	{FILE_CMD_2,  icp67_decode_ti_11_2},
	{FILE_CMD_4,  icp67_decode_ti_11_4},
	{FILE_CMD_5,  icp67_decode_ti_11_5},
	{FILE_CMD_8,  icp67_decode_ti_11_8},
	{FILE_CMD_10, icp67_decode_ti_11_10},
};

#define FILE_DECODE_TABLE_SIZE (sizeof(g_file_decode_table) / sizeof(g_file_decode_table[0]))

static stru_ti_decode_entry g_zip_decode_table[] =
{
	{TI_30_CMD_1, icp67_decode_ti_30_1},
	{TI_30_CMD_3, icp67_decode_ti_30_3},
};

#define ZIP_DECODE_TABLE_SIZE (sizeof(g_zip_decode_table) / sizeof(g_zip_decode_table[0]))

/* 查表函数 */
static icp67_decode_cb ti_decode_find(uint8_t ti)
{
	unsigned int i;

	for(i = 0; i < TI_DECODE_TABLE_SIZE; i++)
	{
		if(g_ti_decode_table[i].ti == ti)
		{
			return g_ti_decode_table[i].func;
		}
	}

	return NULL;
}

static icp67_decode_cb file_decode_find(uint8_t cmd)
{
	unsigned int i;

	for(i = 0; i < FILE_DECODE_TABLE_SIZE; i++)
	{
		if(g_file_decode_table[i].ti == cmd)
		{
			return g_file_decode_table[i].func;
		}
	}

	return NULL;
}

static icp67_decode_cb zip_decode_find(uint8_t cmd)
{
	unsigned int i;

	for(i = 0; i < ZIP_DECODE_TABLE_SIZE; i++)
	{
		if(g_zip_decode_table[i].ti == cmd)
		{
			return g_zip_decode_table[i].func;
		}
	}

	return NULL;
}

/* =========================== 顶层解码分发 =========================== */

/**
 * @brief ICP67 帧解码分发 — 从帧头读取 TI，查表调用对应解码函数
 * @param p_icp67  协议实例 (含回调表 method)
 * @param p_rx     帧数据 (从 search_frame 定位的完整帧)
 * @param rx_len   帧长度
 * @return 0 解码成功, -1 参数无效或 TI 不支持
 *
 * @note 解码函数内部自行处理:
 *       1) COT (传输原因) 验证
 *       2) MD5 校验 (TI_1/TI_2)
 *       3) rtx_flag 管理 (RX_FLAG/TX_FLAG)
 *       4) 回调调用 (p_icp67->method.xxx_cb)
 */

int icp67_decode(stru_icp67 *p_icp67, uint8_t *p_rx, uint16_t rx_len)
{
	stru_head       *p_head;
	icp67_decode_cb  func;
	int ret;

	if(NULL == p_icp67 || NULL == p_rx || 0 == rx_len)
	{
		return -1;
	}

	p_head = (stru_head *)p_rx;

	func = ti_decode_find(p_head->ti);
	if(NULL == func)
	{
		LOG_E("not support ti %d", p_head->ti);
		return -1;
	}

	ret = func(p_icp67, p_rx, rx_len);

	return ret;
}

/* =========================== TI_1: 读独立编码参数响应 =========================== */
/*
 * TI_1 流程:
 *   请求(TI_1, COT_5) → 响应(TI_1, COT_7, MD5+参数数据)
 *
 * 解码步骤:
 *   1. 校验 COT=7 (正常确认)
 *   2. 校验 MD5 与配置一致
 *   3. 遍历参数列表，逐个调用 ao_pop_out_cb
 *   4. 设置 RX_FLAG (表示处理完毕)
 *
 * 数据结构: stru_ti_1_2 { md5[16], num, data[] }
 *   每个 data 条目: stru_ti_1_2_data_info { addr, type, len, data[] }
 */

static int icp67_decode_ti_1(stru_icp67 *p_icp67, uint8_t *p_rx, uint16_t rx_len)
{
	stru_head  *p_head;
	stru_ti_1_2 *p_asdu;
	uint16_t    pos;
	uint8_t     i;

	if(NULL == p_icp67 || NULL == p_rx || 0 == rx_len)
	{
		LOG_E("icp67_decode_ti_1 param error");
		return -1;
	}

	p_head = (stru_head *)p_rx;
	p_asdu = (stru_ti_1_2 *)p_head->data;

	if(COT_7 != p_head->cot)
	{
		LOG_E("icp67_decode_ti_1 COT_7 != p_head->cot, COT_7=%d, p_head->cot=%d", COT_7, p_head->cot);
		return -1;
	}

	if(0 != memcmp(p_icp67->md5, p_asdu->md5, ICP67_MD5_LEN))
	{
		LOG_E("icp67_decode_ti_1 md5 error");
		return -1;
	}

	{
		uint16_t asdu_len = (uint16_t)(rx_len - ICP67_FRAME_OVERHEAD); /* 减去帧头开销 */ 

		pos = 0;
		for(i = 0; p_icp67->method.ao_pop_out_cb && i < p_asdu->num; i++)
		{
			stru_ti_1_2_data_info *p_info;

			if(pos + sizeof(stru_ti_1_2_data_info) > asdu_len)
			{
				LOG_E("icp67_decode_ti_1: frame too short for entry header, pos=%d", pos);
				break;
			}

			p_info = (stru_ti_1_2_data_info *)&p_asdu->data[pos];

			if(pos + sizeof(stru_ti_1_2_data_info) + p_info->data_len > asdu_len)
			{
				LOG_E("icp67_decode_ti_1: data_len overflow, pos=%d, data_len=%d", pos, p_info->data_len);
				break;
			}

			pos += sizeof(stru_ti_1_2_data_info) + p_info->data_len;

			p_icp67->method.ao_pop_out_cb(p_icp67, p_info->data_addr,
				p_info->data_type, p_info->data_len, p_info->data);
		}
	}

	icp67_rtx_flag_set(p_icp67, ICP67_RX_FLAG, 0, 0);

	return 0;
}

/* =========================== TI_2: 写独立编码参数响应 =========================== */

static int icp67_decode_ti_2(stru_icp67 *p_icp67, uint8_t *p_rx, uint16_t rx_len)
{
	stru_head  *p_head;
	stru_ti_1_2 *p_asdu;

	if(NULL == p_icp67 || NULL == p_rx || 0 == rx_len)
	{
		LOG_E("icp67_decode_ti_2 param error");
		return -1;
	}

	p_head = (stru_head *)p_rx;
	p_asdu = (stru_ti_1_2 *)p_head->data;

	if(COT_7 != p_head->cot)
	{
		LOG_E("icp67_decode_ti_2 COT_7 != p_head->cot");
		return -1;
	}

	if(0 != memcmp(p_icp67->md5, p_asdu->md5, ICP67_MD5_LEN))
	{
		LOG_E("icp67_decode_ti_2 md5 error");
		return -1;
	}

	icp67_rtx_flag_set(p_icp67, ICP67_RX_FLAG, 0, 0);

	return 0;
}

/* =========================== TI_3: 读自定义组合编码参数响应 (分帧传输) =========================== */
/*
 * TI_3 是唯一支持分帧传输的消息类型:
 *   请求: 发送端发出 TI_3 COT_5 请求
 *   响应: 下级设备返回 TI_3 COT_7，带 follow 标志
 *        follow=1: 还有后续帧，需继续请求
 *        follow=0: 最后一帧
 *
 * 分帧请求机制 (本函数内):
 *   if(follow): 构造续帧请求 frame_no=offset, 发送 → TX_FLAG
 *   else:      设置 RX_FLAG 表示传输完成
 *
 * 数据结构: stru_ti_3_follow { total, frame_no, follow, num, data[] }
 *   total:    总参数个数 (所有帧)
 *   frame_no: 当前帧的起始索引
 *   follow:   1=还有后续帧, 0=最后一帧
 *   num:      本帧参数个数
 */

static int icp67_decode_ti_3(stru_icp67 *p_icp67, uint8_t *p_rx, uint16_t rx_len)
{
	stru_head       *p_head;
	stru_ti_3_follow *p_asdu;

	if(NULL == p_icp67 || NULL == p_rx || 0 == rx_len)
	{
		LOG_E("icp67_decode_ti_3 param error");
		return -1;
	}

	p_head = (stru_head *)p_rx;

	if(COT_7 != p_head->cot)
	{
		LOG_E("icp67_decode_ti_3 COT_7 != p_head->cot");
		return -1;
	}

	p_asdu = (stru_ti_3_follow *)p_head->data;

	LOG_I("ti 3 decode, total %d, frame no %d, follow %d, num %d",
		p_asdu->total, p_asdu->frame_no, p_asdu->follow, p_asdu->num);

	if(p_icp67->method.iec_point_tbl_pop_out_cb)
	{
		p_icp67->method.iec_point_tbl_pop_out_cb(p_icp67, p_head->info_addr,
			p_asdu->num, p_asdu->data);
	}

	/* 分帧续传: follow=1 时发送续帧请求 */
	if(p_asdu->follow)
	{
		uint8_t  *p_tx   = p_icp67->tx;
		uint16_t  tx_len = 0;
		uint16_t  offset = p_asdu->frame_no + p_asdu->num;

		icp67_make_head(ENUM_DEV_TYPE_SYS, p_head->ti, COT_7, p_head->info_addr, p_tx, &tx_len);

		{
			stru_ti_3_follow *p_tx_asdu = (stru_ti_3_follow *)&p_tx[tx_len];

			p_tx_asdu->total    = p_asdu->total;
			p_tx_asdu->frame_no = offset;
			p_tx_asdu->follow   = p_asdu->follow;
			p_tx_asdu->num      = 0; /* 续帧请求不携带参数数据 */
			tx_len += sizeof(stru_ti_3_follow);
		}

		icp67_make_tail(p_tx, &tx_len);

		p_icp67->tx_len = tx_len;
		p_icp67->send_cb(p_tx, tx_len, p_icp67->arg);

		icp67_rtx_flag_set(p_icp67, ICP67_TX_FLAG, 0, 0);
	}
	else
	{
		icp67_rtx_flag_set(p_icp67, ICP67_RX_FLAG, 0, 0);
	}

	return 0;
}

/* =========================== TI_4: 写自定义组合编码参数响应 (空桩) =========================== */

static int icp67_decode_ti_4(stru_icp67 *p_icp67, uint8_t *p_rx, uint16_t rx_len)
{
	(void)p_rx;
	(void)rx_len;

	LOG_E("TI_4 not supported");
	icp67_rtx_flag_set(p_icp67, ICP67_RX_FLAG, 0, 0);

	return 0;
}

/* =========================== TI_5: 终端时间响应 =========================== */

static int icp67_decode_ti_5(stru_icp67 *p_icp67, uint8_t *p_rx, uint16_t rx_len)
{
	stru_head *p_head;
	stru_ti_5  *p_asdu;

	if(NULL == p_icp67 || NULL == p_rx || 0 == rx_len)
	{
		LOG_E("icp67_decode_ti_5 param error");
		return -1;
	}

	p_head = (stru_head *)p_rx;

	if(COT_7 != p_head->cot)
	{
		LOG_E("icp67_decode_ti_5 COT_7 != p_head->cot");
		return -1;
	}

	p_asdu = (stru_ti_5 *)p_head->data;

	LOG_I("tm set success: %04d-%02d-%02d %02d:%02d:%02d.%03d",
		p_asdu->year + 2000, p_asdu->month, p_asdu->day,
		p_asdu->hour, p_asdu->min, p_asdu->ms / 1000, p_asdu->ms % 1000);

	icp67_rtx_flag_set(p_icp67, ICP67_RX_FLAG, 0, 0);

	return 0;
}

/* =========================== TI_6: 终端状态读取响应 =========================== */

static int icp67_decode_ti_6(stru_icp67 *p_icp67, uint8_t *p_rx, uint16_t rx_len)
{
	stru_head *p_head;
	stru_ti_6  *p_asdu;
	uint16_t   pos;
	uint16_t   i;

	if(NULL == p_icp67 || NULL == p_rx || 0 == rx_len)
	{
		LOG_E("icp67_decode_ti_6 param error");
		return -1;
	}

	p_head = (stru_head *)p_rx;

	if(COT_7 != p_head->cot)
	{
		LOG_E("icp67_decode_ti_6 COT_7 != p_head->cot");
		return -1;
	}

	p_asdu = (stru_ti_6 *)p_head->data;

	{
		uint16_t asdu_len = (uint16_t)(rx_len - ICP67_FRAME_OVERHEAD);

		pos = 0;
		for(i = 0; p_icp67->method.self_check_pop_out_cb && i < p_asdu->st_num; i++)
		{
			stru_data_info *p;

			if(pos + sizeof(stru_data_info) > asdu_len)
			{
				LOG_E("icp67_decode_ti_6: frame too short for entry header, pos=%d", pos);
				break;
			}

			p = (stru_data_info *)&p_asdu->st_data[pos];

			if(pos + sizeof(stru_data_info) + p->data_len > asdu_len)
			{
				LOG_E("icp67_decode_ti_6: data_len overflow, pos=%d, data_len=%d", pos, p->data_len);
				break;
			}

			pos += sizeof(stru_data_info) + p->data_len;

			p_icp67->method.self_check_pop_out_cb(p_icp67, p, i);
		}
	}

	icp67_rtx_flag_set(p_icp67, ICP67_RX_FLAG, 0, 0);

	return 0;
}

/* =========================== TI_9: 升级响应 =========================== */

static int icp67_decode_ti_9(stru_icp67 *p_icp67, uint8_t *p_rx, uint16_t rx_len)
{
	stru_head *p_head;
	uint8_t    result;

	if(NULL == p_icp67 || NULL == p_rx || 0 == rx_len)
	{
		LOG_E("icp67_decode_ti_9 param error");
		return -1;
	}

	p_head = (stru_head *)p_rx;

	if(COT_7 != p_head->cot)
	{
		LOG_E("icp67_decode_ti_9 COT_7 != p_head->cot");
		return -1;
	}

	result = p_head->data[0];

	if(UP_RESULT_1 != result)
	{
		LOG_E("icp67_decode_ti_9 UP_RESULT_1 != result, result=%d", result);
		return -1;
	}

	LOG_I("up success");
	icp67_rtx_flag_set(p_icp67, ICP67_RX_FLAG, 0, 0);

	return 0;
}

/* =========================== TI_11: 文件操作响应 (分发) =========================== */

static int icp67_decode_ti_11(stru_icp67 *p_icp67, uint8_t *p_rx, uint16_t rx_len)
{
	stru_head       *p_head;
	uint8_t          cmd;
	icp67_decode_cb  func;

	if(NULL == p_icp67 || NULL == p_rx || 0 == rx_len)
	{
		LOG_E("icp67_decode_ti_11 param error");
		return -1;
	}

	p_head = (stru_head *)p_rx;

	if(COT_7 != p_head->cot)
	{
		LOG_E("icp67_decode_ti_11 COT_7 != p_head->cot");
		return -1;
	}

	cmd = p_head->data[0];

	if(p_head->len > 11)
	{
		func = file_decode_find(cmd);
		if(NULL != func)
		{
			func(p_icp67, p_rx, rx_len);
		}
	}

	return 0;
}

/* =========================== TI_30: 录波文件压缩响应 (子命令分发) =========================== */
/*
 * TI_30 处理录波文件的分目录和分文件传输:
 *   子命令:
 *     TI_30_CMD_1: 压缩目录
 *     TI_30_CMD_3: 压缩文件内容
 *
 * COT 校验: COT_5 (请求) — 来自采样板的主动上报
 * 通过 zip_decode_find() 查表分发到对应子命令函数
 */

static int icp67_decode_ti_30(stru_icp67 *p_icp67, uint8_t *p_rx, uint16_t rx_len)
{
	stru_head       *p_head;
	uint8_t          cmd;
	icp67_decode_cb  func;

	if(NULL == p_icp67 || NULL == p_rx || 0 == rx_len)
	{
		LOG_E("icp67_decode_ti_30 param error");
		return -1;
	}

	p_head = (stru_head *)p_rx;

	if(COT_5 != p_head->cot)
	{
		LOG_E("icp67_decode_ti_30 COT_5 != p_head->cot");
		return -1;
	}

	cmd = p_head->data[0];

	func = zip_decode_find(cmd);
	if(NULL != func)
	{
		func(p_icp67, p_rx, rx_len);
	}

	return 0;
}

/* =========================== TI_200/201/202: 遥测/遥信/计量传输 =========================== */
/*
 * 采样板主动上报的实时数据:
 *   TI_200: 遥测 (MX) — 每点 4 字节 float
 *   TI_201: 遥信 (ST) — 每点 1 字节 uint8
 *   TI_202: 电度 (DD) — 每点 4 字节 float
 *
 * 公共帧结构: stru_ti_200_201_202 { num, addr, data[] }
 *   num:  本帧数据点数
 *   addr: 起始地址 (info_addr 用于索引)
 *   data: num 个数据项，每个 sizeof(float) 或 1 byte
 *
 * 不校验 COT (注释掉)，支持上行主动上报
 */

static int icp67_decode_ti_200(stru_icp67 *p_icp67, uint8_t *p_rx, uint16_t rx_len)
{
	stru_head            *p_head;
	stru_ti_200_201_202  *p_asdu;
	uint16_t              pos;
	uint16_t              i;
	uint16_t              asdu_len;

	if(NULL == p_icp67 || NULL == p_rx || 0 == rx_len)
	{
		LOG_E("icp67_decode_ti_200 param error");
		return -1;
	}

	p_head = (stru_head *)p_rx;
	p_asdu = (stru_ti_200_201_202 *)p_head->data;

	if(rx_len < ICP67_FRAME_OVERHEAD)
	{
		LOG_E("icp67_decode_ti_200: frame too short");
		return -1;
	}
	asdu_len = (uint16_t)(rx_len - ICP67_FRAME_OVERHEAD);

	pos = 0;
	for(i = 0; p_icp67->method.mx_trans_cb && i < p_asdu->num; i++)
	{
		if(pos + sizeof(float) > asdu_len)
		{
			LOG_E("icp67_decode_ti_200: data overflow, num=%d, pos=%d", p_asdu->num, pos);
			break;
		}
		p_icp67->method.mx_trans_cb(p_icp67, p_asdu->addr + i,
			*(float *)&p_asdu->data[pos]);
		pos += sizeof(float);
	}

	return 0;
}

/* =========================== TI_201: 遥信传输 =========================== */

static int icp67_decode_ti_201(stru_icp67 *p_icp67, uint8_t *p_rx, uint16_t rx_len)
{
	stru_head            *p_head;
	stru_ti_200_201_202  *p_asdu;
	uint16_t              pos;
	uint16_t              i;
	uint16_t              asdu_len;

	if(NULL == p_icp67 || NULL == p_rx || 0 == rx_len)
	{
		LOG_E("icp67_decode_ti_201 param error");
		return -1;
	}

	p_head = (stru_head *)p_rx;
	p_asdu = (stru_ti_200_201_202 *)p_head->data;

	if(rx_len < ICP67_FRAME_OVERHEAD)
	{
		LOG_E("icp67_decode_ti_201: frame too short");
		return -1;
	}
	asdu_len = (uint16_t)(rx_len - ICP67_FRAME_OVERHEAD);

	pos = 0;
	for(i = 0; p_icp67->method.st_trans_cb && i < p_asdu->num; i++)
	{
		if(pos + 1 > asdu_len)
		{
			LOG_E("icp67_decode_ti_201: data overflow, num=%d, pos=%d", p_asdu->num, pos);
			break;
		}
		p_icp67->method.st_trans_cb(p_icp67, p_asdu->addr + i,
			p_asdu->data[pos++]);
	}

	return 0;
}

/* =========================== TI_202: 计量传输 =========================== */

static int icp67_decode_ti_202(stru_icp67 *p_icp67, uint8_t *p_rx, uint16_t rx_len)
{
	stru_head            *p_head;
	stru_ti_200_201_202  *p_asdu;
	uint16_t              pos;
	uint16_t              i;
	uint16_t              asdu_len;

	if(NULL == p_icp67 || NULL == p_rx || 0 == rx_len)
	{
		LOG_E("icp67_decode_ti_202 param error");
		return -1;
	}

	p_head = (stru_head *)p_rx;
	p_asdu = (stru_ti_200_201_202 *)p_head->data;

	if(rx_len < ICP67_FRAME_OVERHEAD)
	{
		LOG_E("icp67_decode_ti_202: frame too short");
		return -1;
	}
	asdu_len = (uint16_t)(rx_len - ICP67_FRAME_OVERHEAD);

	pos = 0;
	for(i = 0; p_icp67->method.dd_trans_cb && i < p_asdu->num; i++)
	{
		if(pos + sizeof(float) > asdu_len)
		{
			LOG_E("icp67_decode_ti_202: data overflow, num=%d, pos=%d", p_asdu->num, pos);
			break;
		}
		p_icp67->method.dd_trans_cb(p_icp67, p_asdu->addr + i,
			*(float *)&p_asdu->data[pos]);
		pos += sizeof(float);
	}

	return 0;
}

/* =========================== TI_203: 遥控交互 (空桩) =========================== */

static int icp67_decode_ti_203(stru_icp67 *p_icp67, uint8_t *p_rx, uint16_t rx_len)
{
	(void)p_rx;
	(void)rx_len;

	LOG_E("TI_203 not supported");
	icp67_rtx_flag_set(p_icp67, ICP67_RX_FLAG, 0, 0);

	return 0;
}

/* =========================== TI_204: SOE 传输 =========================== */

static int icp67_decode_ti_204(stru_icp67 *p_icp67, uint8_t *p_rx, uint16_t rx_len)
{
	stru_head          *p_head;
	stru_ti_204_205_207 *p_asdu;
	uint16_t            pos;
	uint16_t            i;

	if(NULL == p_icp67 || NULL == p_rx || 0 == rx_len)
	{
		LOG_E("icp67_decode_ti_204 param error");
		return -1;
	}

	p_head = (stru_head *)p_rx;

	if(COT_3 != p_head->cot)
	{
		LOG_E("icp67_decode_ti_204 COT_3 != p_head->cot, cot=%d", p_head->cot);
		return -1;
	}

	p_asdu = (stru_ti_204_205_207 *)p_head->data;
	pos = 0;

	for(i = 0; p_icp67->method.soe_trans_cb && i < p_asdu->num; i++)
	{
		stru_st_info *p_st_info = (stru_st_info *)&p_asdu->data[pos];

		pos += sizeof(stru_st_info);

		p_icp67->method.soe_trans_cb(p_icp67, p_st_info);
	}

	return 0;
}

/* =========================== TI_205: 故障事件传输 =========================== */
/*
 * 故障事件包含 ST (遥信) 和 MX (遥测) 混合数据:
 *   帧结构: stru_ti_204_205_207 { num, data[] }
 *   data[] 格式 (每事件):
 *     [st_num:1B] [st_info:st_num*7B] [mx_num:1B] [mx_info:mx_num*6B]
 *
 * 解码策略:
 *   使用固定大小数组 (MAX_FAULT_ST_INFO=64, MAX_FAULT_MX_INFO=64)
 *   逐事件解析 st_num/mx_num，复制到临时数组
 *   构造 stru_fault_info 后调用 fault_trans_cb
 *
 * @note 固定数组替代了原 C++ 的 std::vector，
 *       超出 MAX 限制的数据将被截断 (嵌入式环境足够)
 */

static int icp67_decode_ti_205(stru_icp67 *p_icp67, uint8_t *p_rx, uint16_t rx_len)
{
	stru_head          *p_head;
	stru_ti_204_205_207 *p_asdu;
	uint16_t            pos;
	uint16_t            i;
	stru_st_info        st_info_arr[MAX_FAULT_ST_INFO];
	stru_mx_info        mx_info_arr[MAX_FAULT_MX_INFO];
	uint8_t             st_count = 0;
	uint8_t             mx_count = 0;
	stru_fault_info     fault_info;

	if(NULL == p_icp67 || NULL == p_rx || 0 == rx_len)
	{
		LOG_E("icp67_decode_ti_205 param error");
		return -1;
	}

	p_head = (stru_head *)p_rx;

	if(COT_3 != p_head->cot)
	{
		LOG_E("icp67_decode_ti_205 COT_3 != p_head->cot, cot=%d", p_head->cot);
		return -1;
	}

	p_asdu = (stru_ti_204_205_207 *)p_head->data;
	pos = 0;

	for(i = 0; i < p_asdu->num; i++)
	{
		uint8_t j;
		uint8_t st_num = p_asdu->data[pos++];

		for(j = 0; j < st_num && st_count < MAX_FAULT_ST_INFO; j++)
		{
			stru_st_info *p_st_info = (stru_st_info *)&p_asdu->data[pos];

			pos += sizeof(stru_st_info);
			memcpy(&st_info_arr[st_count++], p_st_info, sizeof(stru_st_info));
		}

		{
			uint8_t mx_num = p_asdu->data[pos++];
			uint8_t j;

			for(j = 0; j < mx_num && mx_count < MAX_FAULT_MX_INFO; j++)
			{
				stru_mx_info *p_mx_info = (stru_mx_info *)&p_asdu->data[pos];

				pos += sizeof(stru_mx_info);
				memcpy(&mx_info_arr[mx_count++], p_mx_info, sizeof(stru_mx_info));
			}
		}
	}

	fault_info.st_num    = st_count;
	fault_info.p_st_info = st_info_arr;
	fault_info.mx_num    = mx_count;
	fault_info.p_mx_info = mx_info_arr;

	if(p_icp67->method.fault_trans_cb)
	{
		p_icp67->method.fault_trans_cb(p_icp67, p_asdu->num, &fault_info);
	}

	return 0;
}

/* =========================== TI_207: 遥测扰动传输 =========================== */

static int icp67_decode_ti_207(stru_icp67 *p_icp67, uint8_t *p_rx, uint16_t rx_len)
{
	stru_head          *p_head;
	stru_ti_204_205_207 *p_asdu;
	uint16_t            pos;
	uint16_t            i;

	if(NULL == p_icp67 || NULL == p_rx || 0 == rx_len)
	{
		LOG_E("icp67_decode_ti_207 param error");
		return -1;
	}

	p_head = (stru_head *)p_rx;

	if(COT_3 != p_head->cot)
	{
		LOG_E("icp67_decode_ti_207 COT_3 != p_head->cot, cot=%d", p_head->cot);
		return -1;
	}

	p_asdu = (stru_ti_204_205_207 *)p_head->data;
	pos = 0;

	for(i = 0; p_icp67->method.mx_change_cb && i < p_asdu->num; i++)
	{
		stru_mx_info *p_mx_info = (stru_mx_info *)&p_asdu->data[pos];

		pos += sizeof(stru_mx_info);

		p_icp67->method.mx_change_cb(p_icp67, p_mx_info);
	}

	return 0;
}

/* =========================== TI_11_2: 读目录响应 =========================== */

static int icp67_decode_ti_11_2(stru_icp67 *p_icp67, uint8_t *p_rx, uint16_t rx_len)
{
	stru_head    *p_head;
	stru_ti_11_2 *p_asdu;
	uint16_t      pos;
	uint16_t      i;

	if(NULL == p_icp67 || NULL == p_rx || 0 == rx_len)
	{
		LOG_E("icp67_decode_ti_11_2 param error");
		return -1;
	}

	p_head = (stru_head *)p_rx;
	p_asdu = (stru_ti_11_2 *)p_head->data;

	pos = 0;

	for(i = 0; p_icp67->method.dir_pop_out_cb && i < p_asdu->num; i++)
	{
		uint8_t  len;
		uint8_t  name[ICP67_NAME_MAX];
		uint32_t attr;
		uint32_t size;
		uint8_t  follow;

		len = p_asdu->data[pos++];
		memcpy(name, p_asdu->data + pos, len);
		name[len] = '\0';
		pos += len;
		attr = *(uint32_t *)&p_asdu->data[pos];
		pos += sizeof(uint32_t);
		size = *(uint32_t *)&p_asdu->data[pos];
		pos += sizeof(uint32_t);

		follow = (0 == p_asdu->follow && i == (p_asdu->num - 1)) ? 0 : 1;

		p_icp67->method.dir_pop_out_cb(p_icp67, name, len, attr, size, follow);
	}

	icp67_rtx_flag_set(p_icp67, ICP67_RX_FLAG, 0, 0);

	return 0;
}

/* =========================== TI_11_4: 读文件激活响应 =========================== */

static int icp67_decode_ti_11_4(stru_icp67 *p_icp67, uint8_t *p_rx, uint16_t rx_len)
{
	stru_head    *p_head;
	stru_ti_11_4 *p_asdu;
	uint16_t      pos;
	uint8_t       name[ICP67_NAME_MAX];
	uint32_t      id;
	uint32_t      size;
	uint16_t      crc;

	if(NULL == p_icp67 || NULL == p_rx || 0 == rx_len)
	{
		LOG_E("icp67_decode_ti_11_4 param error");
		return -1;
	}

	p_head = (stru_head *)p_rx;
	p_asdu = (stru_ti_11_4 *)p_head->data;

	pos = 0;
	memcpy(name, p_asdu->data, p_asdu->len);
	name[p_asdu->len] = '\0';
	pos += p_asdu->len;
	id   = *(uint32_t *)&p_asdu->data[pos];
	pos += sizeof(uint32_t);
	size = *(uint32_t *)&p_asdu->data[pos];
	pos += sizeof(uint32_t);
	crc  = *(uint16_t *)&p_asdu->data[pos];

	if(p_icp67->method.file_read_act_confirm_cb)
	{
		p_icp67->method.file_read_act_confirm_cb(p_icp67, name, p_asdu->len, id, size, crc);
	}

	icp67_rtx_flag_set(p_icp67, ICP67_RX_FLAG, 0, 0);

	return 0;
}

/* =========================== TI_11_5: 读文件内容 =========================== */

static int icp67_decode_ti_11_5(stru_icp67 *p_icp67, uint8_t *p_rx, uint16_t rx_len)
{
	stru_head    *p_head;
	stru_ti_11_5 *p_asdu;

	if(NULL == p_icp67 || NULL == p_rx || 0 == rx_len)
	{
		LOG_E("icp67_decode_ti_11_5 param error");
		return -1;
	}

	p_head = (stru_head *)p_rx;
	p_asdu = (stru_ti_11_5 *)p_head->data;

	if(p_asdu->data[p_asdu->len] != crc_check_sum(p_asdu->data, p_asdu->len))
	{
		LOG_E("icp67_decode_ti_11_5 crc error");
		return -1;
	}

	if(p_icp67->method.file_read_cb)
	{
		p_icp67->method.file_read_cb(p_icp67, p_asdu->id, p_asdu->offset,
			p_asdu->follow, p_asdu->data, p_asdu->len);
	}

	icp67_rtx_flag_set(p_icp67, ICP67_RX_FLAG, 0, 0);

	return 0;
}

/* =========================== TI_11_8: 写文件激活响应 =========================== */

static int icp67_decode_ti_11_8(stru_icp67 *p_icp67, uint8_t *p_rx, uint16_t rx_len)
{
	stru_head    *p_head;
	stru_ti_11_8 *p_asdu;
	uint16_t      pos;
	uint8_t       name[ICP67_NAME_MAX];
	uint32_t      id;
	uint32_t      size_tmp;

	if(NULL == p_icp67 || NULL == p_rx || 0 == rx_len)
	{
		LOG_E("icp67_decode_ti_11_8 param error");
		return -1;
	}

	p_head = (stru_head *)p_rx;
	p_asdu = (stru_ti_11_8 *)p_head->data;

	if(FILE_WRITE_ACT_0 != p_asdu->result)
	{
		LOG_E("icp67_decode_ti_11_8 result error, result=%d", p_asdu->result);
		return -1;
	}

	pos = 0;
	memcpy(name, p_asdu->data, p_asdu->len);
	name[p_asdu->len] = '\0';
	pos += p_asdu->len;
	id       = *(uint32_t *)&p_asdu->data[pos];
	pos     += sizeof(uint32_t);
	size_tmp = *(uint32_t *)&p_asdu->data[pos];

	if(p_icp67->method.file_write_act_confirm_cb)
	{
		p_icp67->method.file_write_act_confirm_cb(p_icp67, p_asdu->result,
			name, p_asdu->len, id, size_tmp);
	}

	icp67_rtx_flag_set(p_icp67, ICP67_RX_FLAG, 0, 0);

	return 0;
}

/* =========================== TI_11_10: 写文件内容响应 =========================== */

static int icp67_decode_ti_11_10(stru_icp67 *p_icp67, uint8_t *p_rx, uint16_t rx_len)
{
	stru_head     *p_head;
	stru_ti_11_10 *p_asdu;

	if(NULL == p_icp67 || NULL == p_rx || 0 == rx_len)
	{
		LOG_E("icp67_decode_ti_11_10 param error");
		return -1;
	}

	p_head = (stru_head *)p_rx;
	p_asdu = (stru_ti_11_10 *)p_head->data;

	if(FILE_WRITE_CONT_0 == p_asdu->result)
	{
		if(p_icp67->method.file_write_end_cb)
		{
			p_icp67->method.file_write_end_cb(p_icp67, p_asdu->result,
				p_asdu->id, p_asdu->offset, p_asdu->md5);
		}
	}
	else if(FILE_WRITE_CONT_1 == p_asdu->result)
	{
		if(p_icp67->method.file_write_confirm_cb)
		{
			p_icp67->method.file_write_confirm_cb(p_icp67, p_asdu->result,
				p_asdu->id, p_asdu->offset);
		}
	}
	else
	{
		LOG_E("icp67_decode_ti_11_10 result error, result=%d", p_asdu->result);
		return -1;
	}

	icp67_rtx_flag_set(p_icp67, ICP67_RX_FLAG, 0, 0);

	return 0;
}

/* =========================== TI_30_1: 录波文件目录 =========================== */

static int icp67_decode_ti_30_1(stru_icp67 *p_icp67, uint8_t *p_rx, uint16_t rx_len)
{
	stru_head      *p_head;
	stru_ti_30_1   *p_asdu;
	uint8_t         zip_name[ICP67_NAME_MAX];
	uint16_t        pos;
	uint8_t         file_num;
	stru_zip_file_info zip_file_arr[MAX_ZIP_FILE_INFO];
	uint8_t         i;

	if(NULL == p_icp67 || NULL == p_rx || 0 == rx_len)
	{
		LOG_E("icp67_decode_ti_30_1 param error");
		return -1;
	}

	p_head = (stru_head *)p_rx;
	p_asdu = (stru_ti_30_1 *)p_head->data;

	pos = 0;
	memcpy(zip_name, p_asdu->data, p_asdu->len);
	zip_name[p_asdu->len] = '\0';
	pos += p_asdu->len;

	file_num = p_asdu->data[pos++];

	for(i = 0; i < file_num && i < MAX_ZIP_FILE_INFO; i++)
	{
		zip_file_arr[i].id  = i;
		zip_file_arr[i].len = p_asdu->data[pos++];
		memcpy(zip_file_arr[i].name, p_asdu->data + pos, zip_file_arr[i].len);
		zip_file_arr[i].name[zip_file_arr[i].len] = '\0';
		pos += zip_file_arr[i].len;
		zip_file_arr[i].size = *(uint32_t *)&p_asdu->data[pos];
		pos += sizeof(uint32_t);
	}

	if(p_icp67->method.zip_dir_pop_out_cb)
	{
		p_icp67->method.zip_dir_pop_out_cb(p_icp67, p_asdu->zip_type, zip_name,
			p_asdu->len, file_num, zip_file_arr);
	}

	return 0;
}

/* =========================== TI_30_3: 压缩文件内容 =========================== */

static int icp67_decode_ti_30_3(stru_icp67 *p_icp67, uint8_t *p_rx, uint16_t rx_len)
{
	stru_head    *p_head;
	stru_ti_30_3 *p_asdu;

	if(NULL == p_icp67 || NULL == p_rx || 0 == rx_len)
	{
		LOG_E("icp67_decode_ti_30_3 param error");
		return -1;
	}

	p_head = (stru_head *)p_rx;
	p_asdu = (stru_ti_30_3 *)p_head->data;

	if(p_icp67->method.zip_file_pop_out_cb)
	{
		p_icp67->method.zip_file_pop_out_cb(p_icp67, p_asdu->file_no,
			p_asdu->offset, p_asdu->data, p_asdu->len);
	}

	return 0;
}
