#include "jxct_protocol.h"
#include "cmsis_os.h"
#include "assertions.h"
#include "inflash.h"

extern u_int8_t rs485_out_buff[50];

/* ¾²Ì¬º¯ÊýÉêÃ÷ */
static void send_uart_pack(device_handle device,FRT_MsgFunctionCode_e cmd_type, const void *data, u_int16_t len);
static void FRT_MsgProc_ReadRegister(device_handle device, void *pMsg); 
static u_int16_t FRT_ReadReg(unsigned char regId);
static u_int16_t FRT_ReadRegMinWindDiretion(void *pMsg);
static u_int16_t FRT_ReadRegAverageWindDirection(void *pMsg);
static u_int16_t FRT_ReadRegMaxWindDirection(void *pMsg);
static u_int16_t FRT_ReadRegMinWindSpeed(void *pMsg);
static u_int16_t FRT_ReadRegAverageWindSpeed(void *pMsg);
static u_int16_t FRT_ReadRegMaxWindSpeed(void *pMsg);
static u_int16_t FRT_ReadRegTemperature(void *pMsg);
static u_int16_t FRT_ReadRegHumidity(void *pMsg);
static u_int16_t FRT_ReadRegPressure(void *pMsg);
static u_int16_t FRT_ReadRegRain(void *pMsg);
static u_int16_t FRT_ReadRegPrecipitationIntensity(void *pMsg);
static u_int16_t FRT_ReadRegDeviceAddr(void *pMsg);
static void pdebug_mcs_info();

/* ¹¦ÄÜÂë´¦Àí±í */
FRT_FuncionMsgProcTable_s g_MsgTbl[] =
{
    { FRT_FUNCTION_CODE_READ_REGISTER,   FRT_MsgProc_ReadRegister  },
   // { FRT_FUNCTION_CODE_WRITE_REGISTER,  FRT_MsgProc_WriteRegister },
};

/* ¼Ä´æÆ÷´¦Àí±í */
FRT_RegProcTable_s g_RegTbl[] =
{
    { FRT_REGISTER_MIN_WIND_DIRECTION,       FRT_ReadRegMinWindDiretion        },
    { FRT_REGISTER_AVERAGE_WIND_DIRECTION,   FRT_ReadRegAverageWindDirection   },
    { FRT_REGISTER_MAX_WIND_DIRECTION,       FRT_ReadRegMaxWindDirection       },
    { FRT_REGISTER_MIN_WIND_SPEED,           FRT_ReadRegMinWindSpeed           },
    { FRT_REGISTER_AVERAGE_WIND_SPEED,       FRT_ReadRegAverageWindSpeed       },
    { FRT_REGISTER_MAX_WIND_SPEED,           FRT_ReadRegMaxWindSpeed           },
    { FRT_REGISTER_TEMPERATURE,              FRT_ReadRegTemperature            },
    { FRT_REGISTER_HUMIDITY,                 FRT_ReadRegHumidity               },
    { FRT_REGISTER_PRESSURE,                 FRT_ReadRegPressure               },
    { FRT_REGISTER_RAIN,                     FRT_ReadRegRain                   },
    { FRT_REGISTER_PRECIPITATION_INTENSITY,  FRT_ReadRegPrecipitationIntensity },
    { FRT_REGISTER_DEVICE_ADDR,              FRT_ReadRegDeviceAddr             },
   // { FRT_REGISTER_COMMU_BAUDRATE,           FRT_ReadRegCommuBaudRate          },
   // { FRT_REGISTER_SPEED_AVERAGE_TIME,       FRT_ReadRegSpeedAverageTime       },
   // { FRT_REGISTER_TEMPHUM_UPDATE_TIME,      FRT_ReadRegTempHumUpdateTime      },
   // { FRT_REGISTER_RAIN_POWER_CONTROL,       FRT_ReadRegRainPowerCtl           },
};

/**
  * @brief  modbus crc16Ëã·¨

  * @param  
  * @retval 
  */
unsigned short CRC16(unsigned char *arr_buff, unsigned char len)
{
	unsigned short crc=0xFFFF;
	unsigned char i, j;
	for ( j=0; j<len; j++){   
		crc=crc ^*arr_buff++;
		for ( i=0; i<8; i++){   
			if( ( crc&0x0001) >0){   
				crc=crc>>1;
				crc=crc^ 0xa001;
			}else{
				crc=crc>>1;
      }
		}   
	}   
	return crc;
}

/**
  * @brief  ¶Á×îС·çÏò¼Ä´æÆ÷Öµ
  * @param  
  * @retval 
  */
static u_int16_t FRT_ReadRegMinWindDiretion(void *pMsg)
{   
      u_int16_t value = (u_int16_t)g_stMcs_Para.min_wind_direction *10;
      return value;   
}

/**
  * @brief  ¶Áƽ¾ù·çÏò¼Ä´æÆ÷Öµ
  * @param  
  * @retval 
  */
static u_int16_t FRT_ReadRegAverageWindDirection(void *pMsg)
{   
      u_int16_t value = (u_int16_t)g_stMcs_Para.average_wind_direction *10;
      return value;   
}

/**
  * @brief  ¶Á×î´ó·çÏò¼Ä´æÆ÷Öµ
  * @param  
  * @retval 
  */
static u_int16_t FRT_ReadRegMaxWindDirection(void *pMsg)
{   
      u_int16_t value=(u_int16_t)g_stMcs_Para.max_wind_direction *10;
      return value;   
}

/**
  * @brief  ¶Á×îС·çËټĴæÆ÷Öµ
  * @param  
  * @retval 
  */
static u_int16_t FRT_ReadRegMinWindSpeed(void *pMsg)
{   
      u_int16_t value=(u_int16_t)g_stMcs_Para.min_wind_speed *10;
      return value;   
}

/**
  * @brief  ¶Áƽ¾ù·çËټĴæÆ÷Öµ
  * @param  
  * @retval 
  */
static u_int16_t FRT_ReadRegAverageWindSpeed(void *pMsg)
{   
      u_int16_t value=(u_int16_t)g_stMcs_Para.average_wind_speed *10;
      return value;   
}

/**
  * @brief  ¶Á×î´ó·çËټĴæÆ÷Öµ
  * @param  
  * @retval 
  */
static u_int16_t FRT_ReadRegMaxWindSpeed(void *pMsg)
{   
       u_int16_t value=(u_int16_t)g_stMcs_Para.max_wind_speed *10;
      return value;   
}

/**
  * @brief  ¶ÁζȼĴæÆ÷Öµ
  * @param  
  * @retval 
  */
static u_int16_t FRT_ReadRegTemperature(void *pMsg)
{   
      u_int16_t value= (u_int16_t)g_stMcs_Para.temperature*10;
      return value;   
}

/**
  * @brief  ¶Áʪ¶È¼Ä´æÆ÷Öµ
  * @param  
  * @retval 
  */
static u_int16_t FRT_ReadRegHumidity(void *pMsg)
{   
      u_int16_t value=(u_int16_t)g_stMcs_Para.humidity*10;
      return value;   
}

/**
  * @brief  ¶ÁÆøѹ¼Ä´æÆ÷Öµ
  * @param  
  * @retval 
  */
static u_int16_t FRT_ReadRegPressure(void *pMsg)
{   
      u_int16_t value=8;
      return value;   
}

/**
  * @brief  ¶ÁÓêÁ¿¼Ä´æÆ÷Öµ
  * @param  
  * @retval 
  */
static u_int16_t FRT_ReadRegRain(void *pMsg)
{   
      u_int16_t value=9;
      return value;   
}

/**
  * @brief  ¶Á¹â·øÉäÇ¿¶È¼Ä´æÆ÷Öµ
  * @param  
  * @retval 
  */
static u_int16_t FRT_ReadRegPrecipitationIntensity(void *pMsg)
{   
      u_int16_t value=10;
      return value;   
}

/**
  * @brief  ¶ÁÉ豸µØÖ·¼Ä´æÆ÷Öµ
  * @param  
  * @retval 
  */
static u_int16_t FRT_ReadRegDeviceAddr(void *pMsg)
{   
      u_int16_t value=g_stConfigInfo.addr;
      return value;   
}

/**
  * @brief  ·âװЭÒé·¢ËÍ

  * @param  
  * @retval Êý¾ÝÕýÈ··µ»ØTRUE£¬Êý¾ÝÒì³£·µ»ØFALSE
  */
static void send_uart_pack(device_handle device,FRT_MsgFunctionCode_e cmd_type, const void *data, u_int16_t len)
{    
     memset(rs485_out_buff,0,sizeof(rs485_out_buff));    
     frt_climate_pack_resp *pack = (frt_climate_pack_resp*)rs485_out_buff;
     
     pack->addr        = g_stConfigInfo.addr;
     pack->func        = FRT_FUNCTION_CODE_READ_REGISTER;
     pack->data_len    = len;
     memcpy(pack->data, data, len);
     *(u_int16_t*)&pack->data[len] = CRC16((u_int8_t *)&pack->addr,pack->data_len+3);
     
     uart_dev_write(device,(u_int8_t*)pack,pack->data_len+5);   
}

/**
  * @brief  ±éÀú´¦Àí¼Ä´æÆ÷
  * @param  
  * @retval 
  */
u_int16_t FRT_ReadReg(unsigned char regId)
{   
    for(u_int16_t i = 0; i < sizeof(g_RegTbl) / sizeof(FRT_RegProcTable_s); i++){
      //term_printf("regId:%d, g_RegTbl.regId :%d\r\n",regId,g_RegTbl[i].regId);
      if (regId == g_RegTbl[i].regId){
         return g_RegTbl[i].pRegProc(NULL);
      }
    }
    return 0;
}

/**
  * @brief  ´¦Àí¶ÁÈ¡¼Ä´æÆ÷Êý¾Ý
  * @param  
  * @retval 
  */
void FRT_MsgProc_ReadRegister(device_handle device, void *pMsg)
{    
    static u_int8_t reg_value_buff[2*100]={0x00};
 
    memset(reg_value_buff,0,sizeof(reg_value_buff));
    frt_climate_pack *pack = (frt_climate_pack*)pMsg;
    
    u_int16_t start_reg_addr = (pack->addr_begin_high_byte<<8)| pack->addr_begin_low_byte;
    u_int16_t reg_num= (pack->regnum_begin_high_byte<<8)| pack->regnum_begin_low_byte;
    
    AssertError(start_reg_addr < 100,return, "¶ÁÈ¡¼Ä´æÆ÷ÆðʼµØÖ·´íÎó%d",start_reg_addr);
    AssertError(reg_num < 100,return, "¶ÁÈ¡¼Ä´æÆ÷ÊýÁ¿´íÎó%d",reg_num);
    
    /* ²É¼¯sht30Êý¾Ý */
     AssertError(get_temp_humi_data(&g_stMcs_Para.temperature, &g_stMcs_Para.humidity),g_stMcs_Para.temperature=0;g_stMcs_Para.humidity=0,"²É¼¯sht30ÎÂʪ¶ÈÊý¾Ýʧ°Ü" );

     /* µ÷ÊÔÐÅÏ¢ */
     pdebug_mcs_info();

    for(u_int16_t pos=0; pos <reg_num; pos++){
      *(u_int16_t*)&reg_value_buff[pos*2] = FRT_ReadReg((start_reg_addr+pos));
    }

    send_uart_pack(device, FRT_FUNCTION_CODE_READ_REGISTER, (u_int8_t*)&reg_value_buff, reg_num*2);
}

/**
  * @brief  ¶ÁÈ¡´®¿ÚÊý¾Ý
  * @param  
  * @retval 
  */
static int uart_read_frt_climate_pack(device_handle uart_handle,u_int8_t *buff, u_int32_t buff_size)
{
    u_int32_t offset = 0;
    char c = 0;
    frt_climate_pack *pack = (frt_climate_pack *)buff;  
    
      buff_size--; //Ô¤ÁôÒ»¸ö'\0'λÖà       
       for (offset = 0; offset < buff_size;){ 
           c = uart_dev_in_char(uart_handle);
           buff[offset++] = c;
           if (offset == sizeof(pack->addr)){
              if (pack->addr != g_stConfigInfo.addr){
                   memcpy(buff, buff+1, offset-1);
                   offset--;
                   buff_size--;
             }     
           }else if (offset == FRT_CLIMATE_PACK_SIZE(pack)){ 
                 return offset;
             }        
           }    
       return 0;
}

/**
  * @brief  ´¦ÀíÒ»ÌõÏûÏ¢
  * @param  
  * @retval 
  */
void FRT_MsgHandler(device_handle device, u_int8_t *pMsg, u_int32_t MsgLen)
{   
    frt_climate_pack *pack = (frt_climate_pack*)pMsg;
    
    //AssertErrorNoPrint((CRC16(pMsg, MsgLen-2) == FRT_CLIMATE_PACK_CRC16(pHeader)),return);
    AssertError((CRC16(pMsg, MsgLen-2) == FRT_CLIMATE_PACK_CRC16(pack)),return,"crc16УÑéʧ°Ü");
    AssertError((pack->func == FRT_FUNCTION_CODE_READ_REGISTER) ||\
                (pack->func == FRT_FUNCTION_CODE_WRITE_REGISTER),return,"crc16УÑéʧ°Ü");
    
    for (u_int16_t i = 0; i < sizeof(g_MsgTbl) / sizeof(FRT_FuncionMsgProcTable_s); i++){
        if (pack->func == g_MsgTbl[i].msgId){
            g_MsgTbl[i].pMsgProc(device, pMsg);
        }
    }
}

/**
  * @brief  ¶ÁÈ¡²¢½âÎö´®¿ÚÊý¾Ý
  * @param  
  * @retval 
  */
static u_int8_t rs485_buff[50]={0x00};
void read_and_process_uart_data(device_handle device)
{
  if(uart_dev_char_present(device)){
     osDelay(20);
     memset(rs485_buff,0,sizeof(rs485_buff));     
     int ret = uart_read_frt_climate_pack(device, rs485_buff, sizeof(rs485_buff));
     if(ret > 0){
         FRT_MsgHandler(device, rs485_buff, ret);
     }
   }
}

/* ´òӡ΢ÆøÏóÊý¾Ý */
static void pdebug_mcs_info()
{
    term_printf("min_wind_direction:      %.2f\r\n", g_stMcs_Para.min_wind_direction);
    term_printf("average_wind_direction:  %.2f\r\n", g_stMcs_Para.average_wind_direction);
    term_printf("max_wind_direction:      %.2f\r\n", g_stMcs_Para.max_wind_direction);
    term_printf("min_wind_speed:          %.2f\r\n", g_stMcs_Para.min_wind_speed);
    term_printf("average_wind_speed:      %.2f\r\n", g_stMcs_Para.average_wind_speed);
    term_printf("max_wind_speed:          %.2f\r\n", g_stMcs_Para.max_wind_speed);
    term_printf("temperature:             %.2f\r\n", g_stMcs_Para.temperature);
    term_printf("humidity:                %.2f\r\n", g_stMcs_Para.humidity);
    term_printf("precipitation:           %.2f\r\n", g_stMcs_Para.precipitation);
    term_printf("precipitation_intensity: %.2f\r\n", g_stMcs_Para.precipitation_intensity);
    
}


// 30 03 00 00 00 0B 00 2C