#include "proto_modbus_master_leakage.h"
#include "string.h"
#include "stdio.h"
#include "app.h"
#include "app_timer.h"
#include "bsp_Uart.h"
#include "bsp_Flash.h"
#include "app_leakage.h"

#include "proto_print.h"
#include "proto_modbus_lib.h"

#define PROTO_LEAKAGE_2CH_READ_DATA_NUM                       (8)
#define PROTO_LEAKAGE_4CH_READ_DATA_NUM                       (14)
#define PROTO_LEAKAGE_READ_DATA_NUM                           (PROTO_LEAKAGE_2CH_READ_DATA_NUM)        /*读取一个设备寄存器数量*/
#define PROTO_LEAKAGE_GET_CURR_DATA_START_ADDR                (0x0000)

static void proto_leakage_init(proto_leakage_t *p_leakage);

static void proto_leakage_tx_task(proto_leakage_t *p_leakage);
static void proto_leakage_rx_task(u8 *p_data,u16 len,void *other_data);

static void proto_leakage_com1_uart_send(u8 *p_data,u16 len);
static void proto_leakage_com2_uart_send(u8 *p_data,u16 len);
static void proto_leakage_com3_uart_send(u8 *p_data,u16 len);
static void proto_leakage_com4_uart_send(u8 *p_data,u16 len);

proto_leakage_t modbus_leakage[APP_COM_NUM] = 
{
    /*COM1*/
    {
        .init               = proto_leakage_init,
        .tx_task            = proto_leakage_tx_task,
        .uart_send          = proto_leakage_com1_uart_send,
    },
    /*COM2*/
    {
        .init               = proto_leakage_init,
        .tx_task            = proto_leakage_tx_task,
        .uart_send          = proto_leakage_com2_uart_send,
    },
    /*COM3*/
    {
        .init               = proto_leakage_init,
        .tx_task            = proto_leakage_tx_task,
        .uart_send          = proto_leakage_com3_uart_send,
    },
    /*COM4*/
    {
        .init               = proto_leakage_init,
        .tx_task            = proto_leakage_tx_task,
        .uart_send          = proto_leakage_com4_uart_send,
    }
};
    
static void proto_leakage_init(proto_leakage_t *p_leakage)
{
    /*绑定串口解析函数*/
    if(p_leakage == &modbus_leakage[APP_COM1])
    {
        com_to_uart[APP_COM1]->rx_data_analysis = proto_leakage_rx_task;
    }
    else if(p_leakage == &modbus_leakage[APP_COM2])
    {
        com_to_uart[APP_COM2]->rx_data_analysis = proto_leakage_rx_task;
    }
    else if(p_leakage == &modbus_leakage[APP_COM3])
    {
        com_to_uart[APP_COM3]->rx_data_analysis = proto_leakage_rx_task;
    }
    else if(p_leakage == &modbus_leakage[APP_COM4])
    {
        com_to_uart[APP_COM4]->rx_data_analysis = proto_leakage_rx_task;
    }
    /*绑定modbus_id和对应的索引在app_com中完成*/
}


static void proto_leakage_com1_uart_send(u8 *p_data,u16 len)
{
    com_to_uart[APP_COM1]->send(com_to_uart[APP_COM1],p_data,len);
}

static void proto_leakage_com2_uart_send(u8 *p_data,u16 len)
{
    com_to_uart[APP_COM2]->send(com_to_uart[APP_COM2],p_data,len);
}

static void proto_leakage_com3_uart_send(u8 *p_data,u16 len)
{
    com_to_uart[APP_COM3]->send(com_to_uart[APP_COM3],p_data,len);
}

static void proto_leakage_com4_uart_send(u8 *p_data,u16 len)
{
    com_to_uart[APP_COM4]->send(com_to_uart[APP_COM4],p_data,len);
}

/*切换读取的漏液子控*/
static void proto_leakage_switch(proto_leakage_t *p_leakage)
{
    p_leakage->sensor_index++;
    if(p_leakage->sensor_index >= p_leakage->sensor_num)
    {
        p_leakage->sensor_index = 0;
    }
}

static void proto_leakage_tx_curr_data_get(proto_leakage_t *p_leakage)
{
    u16 addr = PROTO_LEAKAGE_GET_CURR_DATA_START_ADDR;
    u8 len = PROTO_LEAKAGE_READ_DATA_NUM;
    u8 id = p_leakage->sensor[p_leakage->sensor_index].comm.id;
    modbus_lib_data_read(id,addr,len,p_leakage->uart_send);
}

static void proto_leakage_tx_task(proto_leakage_t *p_leakage)
{
    u16 i;
    proto_sensor_class_t *p_sensor;
    
    p_sensor = &p_leakage->sensor[p_leakage->sensor_index];
    if(0 == p_leakage->sensor_num)/*没有传感器的COM口不发送*/
    {
        return;
    }
   
    if(0 == (p_sensor->comm.sensor_state_code & (PROTO_LEAKAGE_STATE_CODE_TIME_OUT)))
    {
        if((++p_sensor->comm.tx_time_out_count) > 10)/*连续读取10次 通讯超时*/
        {
            p_sensor->comm.sensor_state_code |= (PROTO_LEAKAGE_STATE_CODE_TIME_OUT);
        }
    }
 
    switch(p_sensor->comm.state)
    {
        case PROTO_LEAKAGE_COMM_STATE_INIT:
        {
        
        }break;
        case PROTO_LEAKAGE_COMM_STATE_CURR_DATA_GET:
        {
            proto_leakage_tx_curr_data_get(p_leakage);
        }break;            
        default:
        {
        
        }break;
    } 
    
        /*通讯超时*/
    if(p_sensor->comm.sensor_state_code & (PROTO_LEAKAGE_STATE_CODE_TIME_OUT))
    {
        for(i=0;i<APP_LEAKAGE_SUB_DEVICE_CH_NUM;i++)        /*清除相关数据*/
        {
            leakage.sub_device_data[p_sensor->comm.leakage_data_index].ch_data[i].state = APP_LEAKAGE_SUB_DEVICE_STATE_TIME_OUT;
            leakage.sub_device_data[p_sensor->comm.leakage_data_index].ch_data[i].distance = 0;
        }
    }
    else
    {
        for(i=0;i<APP_LEAKAGE_SUB_DEVICE_CH_NUM;i++)
        {
            leakage.sub_device_data[p_sensor->comm.leakage_data_index].ch_data[i].state &= (~APP_LEAKAGE_SUB_DEVICE_STATE_TIME_OUT);
        }
    }
    
    p_sensor->comm.state_send_time++;
    if(p_sensor->comm.state_send_time >= 3)    /*进入异常*/
    {
        p_sensor->comm.sensor_state_code |= (p_sensor->comm.sensor_state_code);/*记录异常状态*/
        p_sensor->comm.state_send_time = 0;
        p_sensor->comm.state = PROTO_LEAKAGE_COMM_STATE_DEFAULT;
        proto_leakage_switch(p_leakage);      /*切换设备*/
    }
    

    
}

static void proto_leakage_rx_task(u8 *p_data,u16 len,void *other_data)
{
    u8 send_flag = 0;
    u8 modbus_id,cmd;
    u16 check_crc16,modbus_crc16;
    u16 *p_u16_temp;
    u16 i,ch,temp_value;
    u8 *p_rx_valid;
    
    proto_sensor_class_t *p_sensor;
    proto_leakage_t *p_leakage = NULL;

/***********************查找漏液对象**************************/
    if(other_data == NULL)
    {
        return;
    }
    
    /*查找漏液modbus对象*/
    for(i=0;i<4;i++)
    {
        if( (bsp_uart_t *)other_data == com_to_uart[i] )
        {
            p_leakage = &modbus_leakage[i];
        }
    }
    if(p_leakage == NULL)
    {
        return;
    }
    p_sensor = &p_leakage->sensor[p_leakage->sensor_index];
    
/***********************modbus解析**************************/
    if(p_sensor->comm.id != p_data[0])
    {
        p_data = &p_data[1];
        len -= 1; 
    }
    modbus_id = *p_data;
    cmd = *(p_data+1);
    check_crc16 = p_data[len-2] << 8 | p_data[len-1];
    
    if(modbus_id != p_sensor->comm.id) return ;
    if(cmd != 0x03 && cmd != 0x06 && cmd != 0x10 && cmd != 0x41) return ;

    modbus_crc16 = modbus_lib_crc16(p_data,len-2);
    modbus_crc16 = (modbus_crc16 >> 8) | (modbus_crc16 << 8);
    
    if(check_crc16 != modbus_crc16) return ;
    
    if(cmd == 0x41)
    {
       p_rx_valid = &p_data[6]; 
    }
    
    p_rx_valid = &p_data[3];
    
    
    p_sensor->comm.tx_time_out_count = 0;
    p_sensor->comm.sensor_state_code &= (~PROTO_LEAKAGE_STATE_CODE_TIME_OUT);
    
    switch(p_sensor->comm.state)
    {
        case PROTO_LEAKAGE_COMM_STATE_INIT:
        {

        }break;
        case PROTO_LEAKAGE_COMM_STATE_CURR_DATA_GET:
        {
            /*计算当前设备索引*/
            u8 sensor_index = p_sensor->comm.leakage_data_index;
            u8 sub_device_ch;
            u16 ch_addr_offset[4] = {0,8,16,22};     /*漏液待数据地址偏移*/
            u16 temp;
            
            
            /*子漏液控制器为几通道*/
            if(PROTO_LEAKAGE_4CH_READ_DATA_NUM == PROTO_LEAKAGE_READ_DATA_NUM)
            {
                sub_device_ch = APP_LEAKAGE_SUB_DEVICE_CH_NUM;
            }
            else if(PROTO_LEAKAGE_2CH_READ_DATA_NUM == PROTO_LEAKAGE_READ_DATA_NUM)
            {
                sub_device_ch = 2;
            }
            else
            {
                sub_device_ch = APP_LEAKAGE_SUB_DEVICE_CH_NUM;
            }
            
            
            if(sensor_index >= APP_LEAKAGE_SUB_DEVICE_NUM)
            {
                break;
            }

            /*通道数据重置*/
            for(ch = 0;ch < sub_device_ch;ch++)
            {
                leakage.sub_device_data[sensor_index].ch_data[ch].state = 0;
                leakage.sub_device_data[sensor_index].ch_data[ch].distance = 0;
            }

            /* 心跳包：0x0003*/
            temp_value = (p_rx_valid[6] << 8) | p_rx_valid[7];
            leakage.sub_device_data[sensor_index].heartbeat = temp_value & 0xFF;  

            /*测试模式：0x0007*/
            temp_value = (p_rx_valid[14] << 8) | p_rx_valid[15];
            leakage.sub_device_data[sensor_index].test_mode = temp_value & 0xFF;  
            
            /*漏液数据*/
            for(i=0;i<sub_device_ch;i++)
            {
                ch = i;
                temp = ch_addr_offset[i];
                /*漏液*/
                temp_value = (p_rx_valid[temp + 0] << 8) | p_rx_valid[temp + 1];  
                if(temp_value == 1) 
                {
                    leakage.sub_device_data[sensor_index].ch_data[ch].state |= 
                    APP_LEAKAGE_SUB_DEVICE_STATE_LEAKAGE;                       
                }
                /*断带*/
                temp_value = (p_rx_valid[temp + 2] << 8) | p_rx_valid[temp + 3];  
                if(temp_value == 1) 
                {
                    leakage.sub_device_data[sensor_index].ch_data[ch].state |= 
                    APP_LEAKAGE_SUB_DEVICE_STATE_OPEN;
                }
                /*漏液距离*/
                temp_value = (p_rx_valid[temp + 4] << 8) | p_rx_valid[temp + 5];  
                leakage.sub_device_data[sensor_index].ch_data[ch].distance = temp_value;
            }
        }break;            
    }
    if(send_flag)
    {
        return;
    }
    else
    {
        p_sensor->comm.state = PROTO_LEAKAGE_COMM_STATE_DEFAULT;
        p_sensor->comm.sensor_state_code &= (~(0x00000001 << p_sensor->comm.state));/*消除异常状态*/  
        p_sensor->comm.state_send_time = 0; 
        proto_leakage_switch(p_leakage);
        return;
    }
}



