#include "CJT188.h"
#include "string.h"
#include "timer.h"
#include "gateway_message.h"
#include "tcp_server.h"
#include "data_task.h"

CTJBus_t ctjData;

void cjt_callback(UART_HandleTypeDef *husart)
{ 
  if(__HAL_UART_GET_FLAG(husart, UART_FLAG_RXNE) && __HAL_UART_GET_IT_SOURCE(husart, UART_IT_RXNE))
	{
			if (ctjData.rxIndex < _CJT_RXSIZE - 1)
			{
				ctjData.rxBuf[ctjData.rxIndex] = husart->Instance->DR;
				ctjData.rxIndex++;
			}
			else
			{
				uint8_t data = husart->Instance->DR;
			}
	}
	if ((ctjData.rxIndex > 0) && RESET != __HAL_UART_GET_FLAG(husart, USART_FLAG_IDLE) && __HAL_UART_GET_IT_SOURCE(husart, UART_IT_IDLE))
	{	
		uint8_t i;	
		ctjData.done = 1;	
		i = husart->Instance->SR;
		i = husart->Instance->DR;		
		return;
	}
  ctjData.rxTime = gettick();
}
// ##################################################################################################
bool cjt_sendRaw(uint8_t *data, uint16_t size, uint32_t timeout)
{
	GATEWAY_PARAMS *get;
	get= get_gateway_config_params();	
	while(ctjData.txBusy == 1)
	delay_ms(1);
	ctjData.txBusy = 1;
	memset(ctjData.rxBuf, 0, _CJT_RXSIZE);
	ctjData.rxIndex = 0;
	ctjData.done = 0;
	uint32_t startTime = gettick();
	portENTER_CRITICAL();
	if(get->comProtocol){ // get->protocol  1:232 0:485
		USART_232_Send(data,size);
	}else{
		USART_485_Send(data,size);
	}
	
	portEXIT_CRITICAL();
	ctjData.done=0;
	ctjData.txBusy = 0;

	return true;
}
// ##################################################################################################
uint16_t cjt_receiveRaw(uint32_t timeout)
{
  uint32_t startTime = gettick();
  while (1)
  {
    if (gettick() - startTime> timeout * 1000)
      return 0;
    if (ctjData.done == 1)
    {
      return ctjData.rxIndex;
    }
    delay_ms(5);
  }
}

bool cjt_init(uint32_t timeout)
{
  // HAL_GPIO_WritePin(_MMODBUS_CTRL_GPIO, _MMODBUS_CTRL_PIN, GPIO_PIN_RESET); 此处初始化在485 init过
	HAL_GPIO_WritePin(_CTJ_CTRL_GPIO, _CTJ_CTRL_PIN,GPIO_PIN_RESET);
  memset(&ctjData, 0, sizeof(ctjData));
  ctjData.timeout = timeout;
  return true;
}

/*
*********************************************************************************************************
*	函 数 名: bool cjt_read_meter_data(uint8_t* slaveAddress, uint8_t *data, uint8_t protocol)
*	功能说明: 读取仪表上的数据
*	形   参1: slaveAddress：读取的地址  
*	形   参2:	data：接收的内存地址  
*	形   参3:	protocol：读取的仪表类型 0x10(水表) 0x30(燃气表) 0x40(电表)
*	返 回 值: true: 成功 false:失败
*********************************************************************************************************
*/
bool cjt_read_meter_data(uint8_t* slaveAddress, double* data, uint8_t protocol)
{
  uint8_t txData[19];
	txData[0] = 0xFE;
	txData[1] = 0xFE;
	txData[2] = 0xFE;							// 引导符
  txData[3] = 0x68;							// 起始帧
	if(protocol == 0x10)					// 水表
		txData[4] = 0x10;							
	else if(protocol == 0x30)			// 燃气表
		txData[4] = 0x30;
	else if(protocol == 0x40)  		// 电表
		txData[4] = 0x40;
  txData[5] = slaveAddress[0];	// 地址	生产流水号最低字节
  txData[6] = slaveAddress[1];	// 地址 生产流水号次高字节
  txData[7] = slaveAddress[2];	// 地址 生产流水号最高字节
	txData[8] = slaveAddress[3];	// 地址 表计生产月份
  txData[9] = slaveAddress[4];	// 地址 表计生产年份
  txData[10] = slaveAddress[5];	// 地址	生产厂商代码低字节
	txData[11] = slaveAddress[6];	// 地址 生产厂商代码高字节
	txData[12] = 0x01;							// 控制码 CTR_0
	txData[13] = 0x03;						// 数据域长度
	txData[14] = 0x90;						// 数据标识DI0
	txData[15] = 0x1F;						// 数据标识DI1
	txData[16] = 0x01;						// 序列号
	uint8_t crc = 0;
	for(uint8_t i = 0; i < 14; i++)
	{
		crc += txData[i + 3];	
	}
	txData[17] = crc;
	txData[18] = 0x16;						// 结束帧
	
  cjt_sendRaw(txData, 19, 100);
  uint16_t recLen = cjt_receiveRaw(ctjData.timeout);
  if (recLen == 0)
    return false;
	for(uint8_t i = 0; i < 12; i++)
	{
		if(ctjData.rxBuf[i] != txData[i])
			return false;
	}
  
	if (ctjData.rxBuf[12] != txData[12] + 0x80)
    return false;
	if (ctjData.rxBuf[14] != txData[14])
    return false;
	if (ctjData.rxBuf[15] != txData[15])
    return false;
	crc = 0;
	for(uint8_t i = 0; i < 20; i++)
	{
		crc += ctjData.rxBuf[i + 3];	
	}
	if (ctjData.rxBuf[23] != crc)
    return false;
	if (ctjData.rxBuf[24] != txData[18])
    return false;

	if(TransparentModeFlag)	return true;

	*data = data_translate_to_float(ctjData.rxBuf);

  return true;
}


/*
*********************************************************************************************************
*	函 数 名: bool cjt_set_addr(uint8_t *addr)
*	功能说明: 设置仪表地址
*	形    参: addr：需要设置的新地址
*	返 回 值: true: 成功 false:失败
*********************************************************************************************************
*/
bool cjt_set_addr(uint8_t *addr)
{ 
	uint8_t txData[26];
	txData[0] = 0xFE;
	txData[1] = 0xFE;
	txData[2] = 0xFE;							// 引导符
  txData[3] = 0x68;							// 起始帧
  txData[4] = 0xAA;							// 水表、燃气表、电表
  txData[5] = 0xAA;							
  txData[6] = 0xAA;							
  txData[7] = 0xAA;							
	txData[8] = 0xAA;							
  txData[9] = 0xAA;							
  txData[10] = 0xAA;							
	txData[11] = 0xAA;							
	txData[12] = 0x15;							// 控制码 CTR_3
	txData[13] = 0x0A;						// 数据域长度
	txData[14] = 0x18;						// 数据标识DI0
	txData[15] = 0xA0;						// 数据标识DI1
	txData[16] = 0x00;						// 序列号
	txData[17] = addr[6];					// 新地址
	txData[18] = addr[5];					// 新地址
	txData[19] = addr[4];					// 新地址
	txData[20] = addr[3];					// 新地址
	txData[21] = addr[2];					// 新地址
	txData[22] = addr[1];					// 新地址
	txData[23] = addr[0];					// 新地址
	
	uint8_t crc = 0;
	for(uint8_t i = 0; i < 21; i++)
	{
		crc += txData[i + 3];	
	}
	txData[24] = crc;	
	txData[25] = 0x16;	
	
	cjt_sendRaw(txData, 26, 100);
  uint16_t recLen = cjt_receiveRaw(ctjData.timeout);
	if (recLen == 0)
    return false;
  if (ctjData.rxBuf[3] != txData[3])
    return false;
	for(uint8_t i = 0; i < 7; i++)
	{
		if(ctjData.rxBuf[i + 5] != txData[23 - i])
			return false;
	}
	if(ctjData.rxBuf[12] != txData[12] + 0x80)
		return false;
	if(ctjData.rxBuf[14] !=	txData[14] && ctjData.rxBuf[15] != txData[15] )
		return false;
	crc = 0;
	for(uint8_t i = 0; i < 14; i++)
	{
		crc += ctjData.rxBuf[i  + 3];	
	}
	if(ctjData.rxBuf[17] != crc)
		return false;
	if(ctjData.rxBuf[18] != txData[25])
		return false;
	
	return true;
}

/*
*********************************************************************************************************
*	函 数 名: bool cjt_read_addr(uint8_t *add)
*	功能说明: 读取仪表地址
*	形    参: data：读取地址的存放地址
*	返 回 值: true: 成功 false:失败
*********************************************************************************************************
*/
bool cjt_read_addr(uint8_t *add)
{
	uint8_t txData[19];
	txData[0] = 0xFE;
	txData[1] = 0xFE;
	txData[2] = 0xFE;							// 引导符
  txData[3] = 0x68;							// 起始帧
  txData[4] = 0xAA;							// 水表、燃气表、电表
  txData[5] = 0xAA;							
  txData[6] = 0xAA;							
  txData[7] = 0xAA;							
	txData[8] = 0xAA;							
  txData[9] = 0xAA;							
  txData[10] = 0xAA;							
	txData[11] = 0xAA;							
	txData[12] = 0x03;							// 控制码
	txData[13] = 0x03;						// 数据域长度
	txData[14] = 0x81;						// 数据标识DI0
	txData[15] = 0x0A;						// 数据标识DI1
	txData[16] = 0x00;						// 序列号
	uint8_t	crc = 0;
	for(uint8_t i = 0; i < 14; i++)
	{
		crc += txData[i + 3];	
	}
	txData[17] = crc;						// crc
	txData[18] = 0x16;					// 结束帧
	 
	cjt_sendRaw(txData, 19, 100);
  uint16_t recLen = cjt_receiveRaw(ctjData.timeout);
  if (recLen == 0)
    return false;
  
	if (ctjData.rxBuf[3] != txData[3])
    return false;
	if (ctjData.rxBuf[12] != txData[12] + 0x80)
    return false;
	for(uint8_t i = 0; i < 4; i++)
	{
		if(ctjData.rxBuf[i + 13] != txData[i + 13])
			return false;
	}
	crc = 0;
	for(uint8_t i = 0; i < 14; i++)
	{
		crc += ctjData.rxBuf[i + 3];	
	}
	if(ctjData.rxBuf[17] != crc)
		return false;
	if(ctjData.rxBuf[18] != txData[18])
		return false;
	
	if(add != NULL)
	{
		for(uint8_t i = 0; i < 7; i++)
		{
			add[6 - i] =	ctjData.rxBuf[i + 5];
		}
	}
	return true;
}

// 将读取的数据转换成double型
double data_translate_to_float(uint8_t* msg)
{
	int val;
	
	val += ((0xff & (msg[17]>>4))*10 +(0xf & msg[17]));
	val += ((0xff & (msg[18]>>4))*10 +(0xf & msg[18])) * my_pow(10,2);
	val += ((0xff & (msg[19]>>4))*10 +(0xf & msg[19])) * my_pow(10,4);
	val += ((0xff & (msg[20]>>4))*10 +(0xf & msg[20])) * my_pow(10,6);

	return (double)(val)/100.0;
}
