#ifndef MODBUS_ESP_H
#define MODBUS_ESP_H

#include <stdint.h>
#include <stddef.h>
#include <stdbool.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"

/**
 * @brief MODBUS功能码定义
 */
typedef enum {
    MODBUS_FUNC_READ_HOLDING_REGISTERS = 0x03,  // 读取保持寄存器
} modbus_function_code_t;

/**
 * @brief MODBUS异常码定义
 */
typedef enum {
    MODBUS_EXCEPTION_ILLEGAL_FUNCTION = 0x01,
    MODBUS_EXCEPTION_ILLEGAL_DATA_ADDRESS = 0x02,
    MODBUS_EXCEPTION_ILLEGAL_DATA_VALUE = 0x03,
    MODBUS_EXCEPTION_SERVER_DEVICE_FAILURE = 0x04,
} modbus_exception_code_t;

/**
 * @brief MODBUS响应结构体
 */
typedef struct {
    uint8_t slave_addr;       // 从机地址
    uint8_t function_code;    // 功能码
    uint8_t byte_count;       // 数据字节数
    uint16_t *registers;      // 寄存器数据（需要调用者释放）
    uint8_t register_count;   // 寄存器数量
    bool is_exception;        // 是否为异常响应
    uint8_t exception_code;   // 异常码（如果是异常响应）
} modbus_response_t;

/**
 * @brief 计算CRC-16 (MODBUS RTU标准)
 * 
 * @param data 数据指针
 * @param len 数据长度
 * @return uint16_t CRC校验值
 */
uint16_t modbus_crc16(const uint8_t *data, size_t len);

/**
 * @brief 验证CRC校验
 * 
 * @param data 数据指针（包含CRC的完整帧）
 * @param len 数据长度（包含CRC的2个字节）
 * @return true CRC校验成功
 * @return false CRC校验失败
 */
bool modbus_verify_crc(const uint8_t *data, size_t len);

/**
 * @brief 构建MODBUS RTU读取保持寄存器请求帧（功能码03）
 * 
 * @param slave_addr 从机地址
 * @param start_addr 起始寄存器地址
 * @param reg_count 读取寄存器数量
 * @param frame 输出帧缓冲区（需要至少8字节）
 * @param frame_len 输出帧长度
 * @return true 构建成功
 * @return false 构建失败（参数错误）
 */
bool modbus_build_read_holding_req(uint8_t slave_addr, uint16_t start_addr, uint16_t reg_count,
                                   uint8_t *frame, size_t *frame_len);

/**
 * @brief 解析MODBUS RTU响应帧（仅支持功能码03）
 * 
 * @param frame 接收到的帧数据
 * @param frame_len 帧长度
 * @param response 解析结果结构体
 * @return true 解析成功
 * @return false 解析失败（CRC错误、格式错误等）
 */
bool modbus_parse_response(const uint8_t *frame, size_t frame_len, modbus_response_t *response);

/**
 * @brief 释放MODBUS响应结构体中的寄存器内存
 * 
 * @param response MODBUS响应结构体
 */
void modbus_free_response(modbus_response_t *response);

/**
 * @brief MODBUS轮询配置结构体
 */
typedef struct {
    int channel_num;           // RS485通道号 (0 或 1)
    uint8_t slave_addr;        // 从机地址
    uint16_t start_addr;       // 起始寄存器地址
    uint16_t reg_count;        // 读取寄存器数量
    uint32_t poll_interval_ms; // 轮询间隔（毫秒）
    bool enabled;              // 是否启用
} modbus_poll_config_t;

/**
 * @brief 启动MODBUS轮询任务
 * 
 * @param config 轮询配置指针
 * @param priority 任务优先级
 * @param stack_size 任务栈大小
 * @return BaseType_t pdTRUE 成功, pdFALSE 失败
 */
BaseType_t modbus_start_poll_task(modbus_poll_config_t *config, UBaseType_t priority, uint32_t stack_size);

/**
 * @brief 停止MODBUS轮询任务
 * 
 * @return 无返回值
 */
void modbus_stop_poll_task(void);

/**
 * @brief 更新轮询配置
 * 
 * @param config 新的轮询配置
 * @return true 更新成功
 * @return false 更新失败
 */
bool modbus_update_poll_config(modbus_poll_config_t *config);

/**
 * @brief 获取当前轮询配置
 * 
 * @return modbus_poll_config_t* 当前配置指针
 */
modbus_poll_config_t* modbus_get_current_config(void);

#endif // MODBUS_ESP_H
