/*
 * Copyright (c) 2006-2021, RT-Thread Development Team
 *
 * SPDX-License-Identifier: Apache-2.0
 *
 * Change Logs:
 * Date           Author       Notes
 * 2024-04-23     lijian       the first version
 */
#include "modbus_rtu.h"
#include <board.h>

Modbus_RTU_t Modbus_RTU;

/**
 * 设置modbus从机地址
 * @param modbus_addr
 */
void set_Modbus_Addr(rt_uint16_t modbus_addr)
{
    Modbus_RTU.modbus_addr = modbus_addr;
}

/**
 * @brief 获取Modbus从机地址
 * @return rt_uint16
 */
rt_uint16_t get_Modbus_Addr()
{
    return Modbus_RTU.modbus_addr;
}

/**
 * 设置modbus寄存器地址
 * @param modbus_reg_addr
 */
void set_Modbus_Reg_Addr(rt_uint16_t modbus_reg_addr)
{
    Modbus_RTU.modbus_reg_addr = modbus_reg_addr;
}

/**
 * @brief 获取Modbus读取寄存器起始地址
 * @return rt_uint16
 */
rt_uint16_t get_Modbus_Reg_Addr()
{
    return Modbus_RTU.modbus_reg_addr;
}

/**
 * @brief 设置Modbus读寄存器数量
 * @return rt_uint16
 */
void set_Modbus_Reg_Num(rt_uint16_t modbus_reg_num)
{
    Modbus_RTU.modbus_reg_num = modbus_reg_num;
}

/**
 * @brief 获取Modbus读寄存器数量
 * @return rt_uint16
 */
rt_uint16_t get_Modbus_Reg_Num()
{
    return Modbus_RTU.modbus_reg_num;
}



//功能码01（0x01）: 读线圈状态（Read Coils）
//功能码02（0x02）: 读离散输入状态（Read Discrete Inputs）
//功能码03（0x03）: 读保持寄存器（Read Holding Registers）
//功能码04（0x04）: 读输入寄存器（Read Input Registers）
//功能码05（0x05）: 写单个线圈（Write Single Coil）
//功能码06（0x06）: 写单个保持寄存器（Write Single Holding Register）
//功能码15（0x0F）: 写多个线圈（Write Multiple Coils）
//功能码16（0x10）: 写多个保持寄存器（Write Multiple Holding Registers）

/**
 * modbus初始化
 */
void Modbus_init()
{

//    Modbus_RTU.modbus_addr = (rt_uint16_t)0x01;
//    Modbus_RTU.modbus_reg_addr = (rt_uint16_t)0x00;
//    Modbus_RTU.modbus_reg_num = (rt_uint16_t)0x02;

    rs485_inst_t *hinst = rs485_create(RS485_SAMPLE_MASTER_SERIAL, RS485_SAMPLE_MASTER_BAUDRATE,
    RS485_SAMPLE_MASTER_PARITY, RS485_SAMPLE_MASTER_PIN, RS485_SAMPLE_MASTER_LVL);

    if (hinst == RT_NULL)
    {
        rt_kprintf("create rs485 instance fail.\n");
        return;
    }

    rs485_set_recv_tmo(hinst, 1000);
    if (rs485_connect(hinst) != RT_EOK)
    {
        rs485_destory(hinst);
        rt_kprintf("rs485 connect fail.\n");
        return;
    }

    rt_uint8_t ctx_send_buf[AGILE_MODBUS_MAX_ADU_LENGTH];
    rt_uint8_t ctx_read_buf[AGILE_MODBUS_MAX_ADU_LENGTH];


    agile_modbus_rtu_t ctx_rtu;
    agile_modbus_t *ctx = &ctx_rtu._ctx;
    agile_modbus_rtu_init(&ctx_rtu, ctx_send_buf, sizeof(ctx_send_buf), ctx_read_buf, sizeof(ctx_read_buf));
    agile_modbus_set_slave(ctx, Modbus_RTU.modbus_addr);  //地址
    rt_kprintf("Modbus Running.\n");


    rt_int8_t send_len;
    rt_int8_t read_len;
    rt_uint8_t i;
    rt_int8_t rc;

    //


    while (1)
    {
        rt_thread_mdelay(1000);


        //if(Modbus_RTU.modbus_func == 3){
            send_len = agile_modbus_serialize_read_registers(ctx, Modbus_RTU.modbus_reg_addr, Modbus_RTU.modbus_reg_num);
//
//        } else if(Modbus_RTU.modbus_func == 1){
//            send_len = agile_modbus_serialize_read_bits(ctx, Modbus_RTU.modbus_reg_addr, Modbus_RTU.modbus_reg_num);
//
//        }

//        rt_kprintf("rs485 send %d datas : ", send_len);
//        for (i = 0; i < send_len; i++) {
//            rt_kprintf("%02X ", ctx->send_buf[i]);
//            }

      //  rt_kprintf("\n");

        read_len = rs485_send_then_recv(hinst, (void *) ctx->send_buf, send_len, ctx->read_buf, ctx->read_bufsz);
        if (read_len < 0)
        {
      //      rt_kprintf("rs485 send datas error.\n");
            break;
        }

        if (read_len == 0)
        {
     //       rt_kprintf("rs485 recv timeout.\n");
            continue;
        }

        ctx->read_buf[read_len] = 0;

//        Bsp_Rs485_Tx(ctx->send_buf, send_len); //
//        int read_len = Bsp_Rs485_Rx(ctx->read_buf, ctx->read_bufsz); //

        if (read_len == 0)
        {
  //          rt_kprintf("Receive timeout.\n");
            continue;
        }
        rc = agile_modbus_deserialize_read_registers(ctx, read_len, Modbus_RTU.hold_register);
        if (rc < 0)
        {
            Modbus_RTU.modbus_rec = 0;

            rt_kprintf("Receive failed.\n");
            if (rc != -1)
                rt_kprintf("Error code:%d\n", -128 - rc);
            continue;
        }

        Modbus_RTU.modbus_rec = 1;

        if (Modbus_RTU.log) {
            rt_kprintf("Hold Registers:");
            for (i = 0; i < 10; i++)
                rt_kprintf("Register [%d]: 0x%04X\n", i, Modbus_RTU.hold_register[i]);
        }

        if (Modbus_RTU.modbus_rec) {
            //get_modbus_rec();
//            MQTT_Send_Modbus(get_modbus_rec());
        }
        rt_kprintf("\r\n\r\n\r\n");
    }

}

void set_modbus_log(rt_uint8_t log){
    Modbus_RTU.log = log;
}

/**
 * 获取modbus读取数据的转换后返回值
 * @return
 */
rt_uint16_t get_modbus_rec(){
    if (Modbus_RTU.modbus_rec) {

        rt_uint8_t high_d=0;
        rt_uint8_t low_d=0;

        if (Modbus_RTU.modbus_reg_num == 2) {
            high_d = Modbus_RTU.hold_register[0];
            low_d = Modbus_RTU.hold_register[1];
            rt_uint16_t rec = (high_d << 8) | low_d;
            return rec;
        }
        Modbus_RTU.modbus_rec =0;
    }
    return 0;
}

//void Bsp_Rs485_Tx(){
//
//}
//
//void Bsp_Rs485_Rx(){
//
//}
//
//static void rs485_sample_master(void *args)
//{
//    const char read_cmd[] = "read datas test\r\n";
//    static rt_uint8_t buf[256];
//    rs485_inst_t *hinst = rs485_create(RS485_SAMPLE_MASTER_SERIAL, RS485_SAMPLE_MASTER_BAUDRATE,
//    RS485_SAMPLE_MASTER_PARITY, RS485_SAMPLE_MASTER_PIN, RS485_SAMPLE_MASTER_LVL);
//
//    if (hinst == RT_NULL)
//    {
//        LOG_E("create rs485 instance fail.");
//        return;
//    }
//
//    rs485_set_recv_tmo(hinst, 1000);
//    if (rs485_connect(hinst) != RT_EOK)
//    {
//        rs485_destory(hinst);
//        LOG_E("rs485 connect fail.");
//        return;
//    }
//
//    while (1)
//    {
//        int len = strlen(read_cmd);
//        len = rs485_send_then_recv(hinst, (void *) read_cmd, len, buf, sizeof(buf));
//        if (len < 0)
//        {
//            LOG_E("rs485 send datas error.");
//            break;
//        }
//
//        if (len == 0)
//        {
//            LOG_D("rs485 recv timeout.");
//            continue;
//        }
//
//        buf[len] = 0;
//        LOG_D("rs485 recv %d datas : %s", len, buf);
//    }
//
//}

//
//#define PORT_NUM        MB_MASTER_USING_PORT_NUM
//#define PORT_BAUDRATE   MB_MASTER_USING_PORT_BAUDRATE
//
//#define PORT_PARITY     MB_PAR_EVEN
//
//#define MB_POLL_CYCLE_MS   500
//
//#define func_Coil       1
//#define func_Holding    3
//
//#define MODBUS_REG_NUM 30

//rt_uint16_t buffer[MODBUS_REG_NUM];
//
///*
// *

// *
// */
//
//void Copy_Holding(rt_uint16_t * Holding, rt_uint16_t reg_num){
//    rt_uint16_t * a = get_modbus_03();
//    for (rt_uint8_t var = 0;  var < reg_num; var++) {
//        Holding[var] = a[var];
//    }
//}
//
//void Copy_Coil(rt_uint16_t * Coil, rt_uint16_t reg_num){
//    unsigned char * a = get_modbus_01();
//    for (rt_uint8_t var = 0;  var < reg_num; var++) {
//        Coil[var] = a[var];
//    }
//}
//
//
//
//void Modbus_Read_Holding_Registers(rt_uint16_t addr, rt_uint16_t reg_addr, rt_uint16_t reg_num, rt_uint16_t * Holding){
//
//    while(1){
//        eMBMasterPoll();
//
//        /*
//         *  ucSndAddr    请求的从机地址，0代表广播。
//            usRegAddr   读寄存器的地址
//            usRegData   读寄存器的数量
//            lTimeOut    请求超时时间。支持永久等待，使用操作系统的永久等待参数即可。
//         */
//        eMBMasterReqReadHoldingRegister(addr, reg_addr, reg_num, 1000);
//
//        rt_thread_mdelay(MB_POLL_CYCLE_MS);
//
//        if (get_Holding_flag()) {
//            Copy_Holding(Holding, reg_num);
//            Modbus_RTU.modbus_rec =1;
//            get_modbus_rec();
//        }
//
//    }
//}
//
//void Modbus_Read_Coils(rt_uint16_t addr, rt_uint16_t reg_addr, rt_uint16_t reg_num, rt_uint16_t * Coil){
//
//    while(1){
//        eMBMasterPoll();
//
//        /*
//         *  ucSndAddr    请求的从机地址，0代表广播。
//            usCoilAddr  读线圈的地址
//            usNCoils    读线圈的数量
//            lTimeOut    请求超时时间。支持永久等待，使用操作系统的永久等待参数即可
//         */
//        eMBMasterReqReadCoils(addr, reg_addr, reg_num, 1000);
//
//        rt_thread_mdelay(MB_POLL_CYCLE_MS);
//        if (get_Coil_flag()) {
//            Copy_Coil(Coil , reg_num);
//            Modbus_RTU.modbus_rec =1;
//        }
//    }
//}
//
//
//void Modbus_config(void){
//
//    eMBMasterInit(MB_RTU, PORT_NUM, PORT_BAUDRATE, PORT_PARITY);
//    eMBMasterEnable();
//
////    if(Modbus_RTU.modbus_func == func_Holding){
//        Modbus_Read_Holding_Registers(Modbus_RTU.modbus_addr, Modbus_RTU.modbus_reg_addr, Modbus_RTU.modbus_reg_num ,buffer);
////    } else if(Modbus_RTU.modbus_func == func_Coil){
////        Modbus_Read_Coils(Modbus_RTU.modbus_addr, Modbus_RTU.modbus_reg_addr, Modbus_RTU.modbus_reg_num , buffer);
////    }
//
//}
//


