#include "includes.h"
#include "device.h"
#include "tax_ctrl.h"
#include "net_proc.h"
#include "oiltank.h"

typedef union {
	u8	c[5];
	u32 i;
} uData_t;

typedef union {
	u32 i;
	float f;
} uData1_t;

system_oiltank_info_t system_oiltank;

//CRC校验（本质和校验）
static u32 _check_sum(u8 buf[], u32 len)
{
    u32 i, check_sum = 0;
	uData_t data;
	
    for(i=0; i< len; i++) {
        check_sum += buf[i];
    }
#if 0
	check_sum = ~check_sum;	
    check_sum &= 0xffff;
    check_sum += 1;
#else
  check_sum &= 0xffff;
  check_sum = 0xffff-check_sum+1;
#endif
	snprintf(data.c, sizeof(data.c), "%04X", check_sum);
    return data.i;
}

static u32 _str_to_hex(uint8_t *data)
{
	u8 i, ch;
	u32 hex = 0;

	//data_dump("====", data, 8);
	for(i = 0;i < 8;i++) {
		if(isdigit(data[i])) {
			ch = data[i] - '0' + 0x0;
		} else if(isalpha(data[i])){
			ch = data[i] - 'A' + 0xA;
		}
		
		hex = (hex<<4)|ch;
	}

	//printf("%08x, %0.2f\r\n", hex, (float)(hex));
	return (hex);
}

int oiltank_data_update(I201_FUELTANK_DATA *p_data)
{
	uData1_t data;
	oiltank_info_t *p_tank = NULL;
	u8 id = 0;

	id = p_data->TT[1] - '0';
	if(id > OILTANK_VALID_COUNT) {
		return 0;
	}
	//data_dump("******", (uint8_t * )p_data, YB_SS160_RCV_DATASIZE);
	p_tank = &system_oiltank.oiltank[id];
	printf("罐号: %c%c\r\n", p_data->TT[0], p_data->TT[1]);
	printf("油品: %c\r\n", p_data->P);
	printf("油罐状态: %c%c%c%c\r\n", p_data->SSSS[0], p_data->SSSS[1], p_data->SSSS[2], p_data->SSSS[3]);
	printf("%c%c 组数据\r\n", p_data->NN[0], p_data->NN[1]);
	p_tank->id = id;
	BIT_SET(system_oiltank.valid, p_tank->id);
	
	p_tank->quality = p_data->P;
	
/*     首先来看单精度浮点型float。
	float占用4字节空间，也就是32位。
	从左向右数，第1位是符号位（0代表正数，1代表负数），接着是8位指数位，剩下的23位是数据位。如下所示
	S EEEEEEEE DDDDDDDDDDDDDDDDDDDDDDD
*/
	
	//1、容积；2、TC 容积；3、罐空；4 高度；5、水位；6、温度；7、水容积 
	p_tank->volume = _str_to_hex(p_data->TankVolume);
	printf("Tank Volume  : 0x%08x\r\n", p_tank->volume);
	//printf("Tank Volume  :%0.2f\r\n", data.f);
	p_tank->oil_volume = _str_to_hex(p_data->NetVolume);
	//printf("Net Volume   :%0.2f\r\n", data.f);
	data.i = _str_to_hex(p_data->CrossVolume);
	//printf("Cross Volume :%0.2f\r\n", data.f);
	p_tank->height = _str_to_hex(p_data->Height);
	//printf("Height       :%0.2f\r\n", data.f);
	data.i = _str_to_hex(p_data->Water);
	//printf("Water        :%0.2f\r\n", data.f);
	p_tank->temperature = _str_to_hex(p_data->Temp);
	//printf("Temp         :%0.2f\r\n", data.f);
	p_tank->water_volume = _str_to_hex(p_data->WaterVolume);
	//printf("Water Volume :%0.2f\r\n", data.f);
	p_tank->valid_num++;
	
	return 0;
}

int oiltank_YB_SS160_cmd_comm(uint8_t uart)
{
	int ret = -1;
	uint8_t rcv_buf[1024], send_buf[128];
	uint32_t i, rcv_size = 0, send_size = YB_SS160_SEND_SIZE, crc;
	RS232_YB_SS160_SEND *p_tank_tx = (RS232_YB_SS160_SEND *)send_buf;
	RS232_YB_SS160_RECEIVE_HEAD *p_tank_rx_head = (RS232_YB_SS160_RECEIVE_HEAD *)rcv_buf;
	RS232_YB_SS160_RECEIVE_TAIL *p_tank_rx_tail = NULL;
	I201_FUELTANK_DATA *p_data = NULL;
	int FuelTank_Num = 0;
	oiltank_info_t *p_tank = NULL;

	/* 查询所有油管数据 */
	//<SOH>i201TT,
	/* <SOH>i201TT
		YYMMDDHHmm 日期和时间（年/月/日/时/分）
		TTpssssNNFFFFFFFF... 
		TTpssssNNFFFFFFFF...
		
		&&CCCC<ETX> 
	*/
	p_tank_tx->SOH = 0x01;
	strcpy((char *)p_tank_tx->FCN_CODE, "i20100");
    p_tank_tx->EXT = 0x03;

	data_dump("YB_SS160 oiltank send", send_buf, send_size);
	uart_msg_send(uart, (char *)p_tank_tx, send_size);
	rcv_size = uart_blocking_read((char *)rcv_buf, uart, 5000);
	if(rcv_size) {
		data_dump("YB_SS160 oiltank recv", rcv_buf, rcv_size);
		if(memcmp((char *)p_tank_rx_head->FCN_CODE, "i20100", sizeof(p_tank_rx_head->FCN_CODE)) == 0) {
			/* check sum */
			p_tank_rx_tail = (RS232_YB_SS160_RECEIVE_TAIL *)(rcv_buf + rcv_size - YB_SS160_RCV_TAILSIZE);
			crc = _check_sum(rcv_buf, rcv_size - YB_SS160_RCV_TAILSIZE + 2);
			printf("headsize : %d, datasize : %d, tailsize : %d, rcv_size : %d, %x, %x, %x\r\n", 
				YB_SS160_RCV_HEADSIZE,
				YB_SS160_RCV_DATASIZE, 
				YB_SS160_RCV_TAILSIZE, rcv_size,
				p_tank_rx_tail->FCN_FLAG, p_tank_rx_tail->CheckCode , crc);
			if((p_tank_rx_tail->FCN_FLAG == YB_SS160_FCN_FLAG)&&
				(p_tank_rx_tail->CheckCode == crc)) {
				rcv_size -= (YB_SS160_RCV_HEADSIZE + YB_SS160_RCV_TAILSIZE);
				FuelTank_Num = rcv_size/YB_SS160_RCV_DATASIZE;
				for(i = 0;i < FuelTank_Num;i++) {
					p_data = (I201_FUELTANK_DATA *)(rcv_buf + YB_SS160_RCV_HEADSIZE + i*YB_SS160_RCV_DATASIZE);
					oiltank_data_update(p_data);
				}
			}
		}
	}

	for(i = 0;i < OILTANK_VALID_COUNT;i++) {		
		if(BIT_IS_SET(system_oiltank.valid, 1<<system_oiltank.current)) {
			p_tank = &system_oiltank.oiltank[i];
			if(p_tank->valid_num == 0) {
				BIT_CLC(system_oiltank.valid, i);
				memset(p_tank, 0, sizeof(oiltank_info_t));
			} else {
				p_tank->valid_num = 0;
			}
		}
	}

	return ret;
}
		
void oiltank_polling(void)
{
	uint8_t uart = OILTANK_UART;

	YTSF_GPIO_RS485_RESET();
	YTSF_GPIO_YTSF_RESET();
	YTSF_GPIO_AB_SET();
	oiltank_YB_SS160_cmd_comm(uart);
}

void oiltank_msg_timer(void *p_tmr, void *p_arg)
{
	inner_msg_format_t *p_msg = NULL;
	uint32_t *p_collect_time = NULL, i;
	gb_oiltank_header_t *p_oiltank_header = NULL;
	oiltank_info_t *p_oiltank_info = NULL;

	if(system_oiltank.valid == 0) {/* 没有有效数据 */
		return ;
	}
	
	p_msg = (inner_msg_format_t *)net_queue_mem_calloc();
	if(p_msg == NULL) {
		return ;
	}
	//HEADER
	p_oiltank_header = (gb_oiltank_header_t *)p_msg->info;
	device_type_and_id_get(&p_oiltank_header->device_type, &p_oiltank_header->device_id);
	p_oiltank_header->device_status = 0;
	p_oiltank_header->oiltank_count = 1;

	//OILTANK_INFO
	for(i = 0;i < OILTANK_VALID_COUNT;i++) {
		system_oiltank.current += i + 1;
		system_oiltank.current = system_oiltank.current%OILTANK_VALID_COUNT;
		if(BIT_IS_SET(system_oiltank.valid, 1<<system_oiltank.current)) {
			break;
		}		
	}

	if(i == OILTANK_VALID_COUNT) {
		return ;
	}
	p_oiltank_info = (oiltank_info_t *)(p_msg->info + GB_OILTANK_HEADER_LEN);
#if 0
	p_oiltank_info->id = 1;
	p_oiltank_info->quality = QUALITY_95;
	p_oiltank_info->volume = 100;
	p_oiltank_info->oil_volume = 200;
	p_oiltank_info->water_volume = 300;
	p_oiltank_info->temperature = 50;
	p_oiltank_info->height = 400;
#else 
	memcpy(p_oiltank_info, &system_oiltank.oiltank[system_oiltank.current], GB_OILTANK_INFO_LEN);
#endif
	//timestamp
	p_collect_time = (uint32_t *)(p_msg->info + GB_OILTANK_HEADER_LEN + GB_OILTANK_INFO_LEN);
	*p_collect_time = RTC_GetCounter();
	net_msg_frame_fill(p_msg, net_msg_type_oiltank, GB_OILTANK_HEADER_LEN + GB_OILTANK_INFO_LEN + 4);
	net_queue_insert((char *)p_msg, sizeof(inner_msg_format_t));
	data_dump(MQTT_UPLINK_TANK_TOPIC, (uint8_t *)p_msg, sizeof(inner_msg_format_t));
}

OS_TMR oiltank_timer;
int oiltank_init(void)
{
	OS_ERR err;
	
	//GUN CHECK，PC0 - PC 3
	GPIO_COMM_Init(RCC_APB2Periph_GPIOC, GPIOC, 
			GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3 , GPIO_Mode_IN_FLOATING, GPIO_Speed_2MHz);

	//SW_PORT_RS485、SW_PORT_AB、SW_PORT_CD、SW_PORT_YTSF
	GPIO_COMM_Init(RCC_APB2Periph_GPIOD, GPIOD, GPIO_Pin_3|GPIO_Pin_4|GPIO_Pin_5|GPIO_Pin_6, GPIO_Mode_Out_PP, GPIO_Speed_2MHz);
	
	//YTSF_REV2
	GPIO_COMM_Init(RCC_APB2Periph_GPIOD, GPIOD, GPIO_Pin_7, GPIO_Mode_IPU, GPIO_Speed_2MHz);

	//YTSF_RST_N
	GPIO_COMM_Init(RCC_APB2Periph_GPIOB, GPIOB, GPIO_Pin_5, GPIO_Mode_Out_PP, GPIO_Speed_2MHz);
	YTSF_GPIO_EN();

	//YTSF_POSITION_N
	GPIO_COMM_Init(RCC_APB2Periph_GPIOB, GPIOB, GPIO_Pin_6, GPIO_Mode_IPU, GPIO_Speed_2MHz);

	//YTSF_EN_N
	GPIO_COMM_Init(RCC_APB2Periph_GPIOB, GPIOB, GPIO_Pin_7, GPIO_Mode_Out_PP, GPIO_Speed_2MHz);
	YTSF_GPIO_DN();
 
	OSTmrCreate(&oiltank_timer, "oiltank_tmr", 
		OILTANK_MSG_PERIOD, OILTANK_MSG_PERIOD, OS_OPT_TMR_PERIODIC, oiltank_msg_timer, NULL, &err);
	OSTmrStart(&oiltank_timer, &err);	
	
	YTSF_GPIO_DN();

	memset(&system_oiltank, 0 ,sizeof(system_oiltank_info_t));
	system_oiltank.valid = 0;
	system_oiltank.current = 0;
	
	return 0;
}
