#include "windows.h"
#include "gas_monitor.h"
#include "SerialPort.h"
#include "database/database.h"
#include <iomanip>
#include "ysp_modbus_slave.h"
#include "common.h"
#include "tchar.h"
/*
	gas_monitor.c 功能描述:
	usb端口接入继电器控制板，控制板上有CH340芯片及microMCU
	通过usb给控制板发特定串口指令数据控制继电器开合
*/

using namespace std;

#if 1	//发布时用这组
#define MIN_SLEEP(min) min*60*1000  
#define PERIOD_MONITOR(min) MIN_SLEEP(min) //监测周期
#define DEFAULT_PERIOD 40
#else	//这一组用于开发测试
#define MIN_SLEEP(min) min*1*1000  
#define PERIOD_MONITOR(min) MIN_SLEEP(min) //监测周期
#define DEFAULT_PERIOD 5	//默认监测周期秒
#endif

#define OVER_THRESHOLD 1 //超过阈值
#define NOT_OVER_THRESHOLD 0 
#define DATA_HAS_CHANGE 1//数据发生变化
#define NORMAL_CLOSE 1 //继电器常闭
#define NORMAL_OPEN 0	//继电器常开
#define BUADRATE_DEFAULT 9600

static unsigned int monitor_period = DEFAULT_PERIOD; //监测周期 mintue
static unsigned int buadrate = BUADRATE_DEFAULT;

float h2_threshold = H2_THRESHOLD; // 各个气体的默认告警阈值
float co_threshold = CO_THRESHOLD;
float co2_threshold = CO2_THRESHOLD;
float ch4_threshold = CH4_THRESHOLD;
float c2h2_threshold = C2H2_THRESHOLD;
float c2h4_threshold = C2H4_THRESHOLD;
float c2h6_threshold = C2H6_THRESHOLD;


static char H2_alert_flag = 0;
static char CO_alert_flag = 0;
static char CO2_alert_flag = 0;

#if 0 //这段代码暂时留着备份 可能后面确实用不到了再删
//H2
cout << "\n    H2 h2_threshold = " << h2_threshold << endl;
cout << "    ysp_data.H2 curr value = " << ysp_data.H2 << endl;
if (ExceedThreshold(ysp_data.H2, h2_threshold)) {
	//超过阈值，uart输出控制信号
	cout << "H2 over" << endl;
	if (last_signal_H2 != OVER_THRESHOLD) {
		cout << "H2 relay normal close" << endl;
		last_signal_H2 = OVER_THRESHOLD;
		uart_signal_arr[H2][0] = DATA_HAS_CHANGE;//第一个byte表示那个数据需要输出信号
		uart_signal_arr[H2][1] = NORMAL_CLOSE;//第二个byte表示该数据输出什么信号
	}
}
else {
	cout << "H2 not over" << endl;
	//在范围内，uart输出控制信号
	if (last_signal_H2 != NOT_OVER_THRESHOLD) {
		cout << "H2 relay normal open" << endl;
		last_signal_H2 = NOT_OVER_THRESHOLD;
		uart_signal_arr[H2][0] = DATA_HAS_CHANGE;//第一个byte表示那个数据需要输出信号
		uart_signal_arr[H2][1] = NORMAL_OPEN;//第二个byte表示该数据输出什么信号
	}
}
#endif


enum data_code_e {
	H2 = 0,
	CO = 1,
	CO2 = 2,
	CH4 = 3,
	C2H2 = 4,
	C2H4 = 5,
	C2H6 = 6,
	Total = 7,
	MAX_ALERT //最大告警数
};
/*
uart_signal_arr[MAX_ALERT][2];
一维数组: 表示气体类型
二维数组: 第一个字节表示该气体是否需要改变继电器状态，第二个字节表示继电器的开关类型
*/
unsigned char uart_signal_arr[MAX_ALERT][2];

//常闭
//顺序和data_code_e一定要一致
static unsigned char uart_close_cmd_arr[MAX_ALERT][3] = {
	{0x00,0xF1,0xFF},
	{0x00,0xF2,0xFF},
	{0x00,0xF3,0xFF},
	{0x00,0xF4,0xFF},
	{0x00,0xF5,0xFF},
	{0x00,0xF6,0xFF},
	{0x00,0xF7,0xFF},
	{0x00,0xF8,0xFF},
};
//常开
//顺序和data_code_e一定要一致
static unsigned char uart_open_cmd_arr[MAX_ALERT][3] = {
	{0x00,0x01,0xFF},
	{0x00,0x02,0xFF},
	{0x00,0x03,0xFF},
	{0x00,0x04,0xFF},
	{0x00,0x05,0xFF},
	{0x00,0x06,0xFF},
	{0x00,0x07,0xFF},
	{0x00,0x08,0xFF},
};

const double eps = 1e-6;
#define Equ(a,b) ((abs((a) - (b))) < (eps)) 
#define More(a,b) (((a) - (b)) > (eps)) 
#define Less(a,b) (((a) - (b)) < -(eps)) 
#define MoreEqu(a,b) (((a) - (b)) > (-eps)) 
#define LessEqu(a,b) (((a) - (b)) < (eps)) 

//浮点数比较,超过阈值则返回1
int ExceedThreshold(float data, float threshold)
{
	if (MoreEqu(data, threshold)) {
		return 1;
	}
	return 0;
}
//监测周期
void xSet_monitor_period(const char* mon_period)
{
	if (mon_period) {
		monitor_period = atoi(mon_period);
		printf("monitor_period=%s\n", mon_period);
		printf("monitor_period=%d\n", monitor_period);
	}
	else {
		monitor_period = DEFAULT_PERIOD;
		printf("GAS_MONITOR_PERIOD is null,use default\n");
	}
}
void xSet_uart_buadrate(const char* uart_buadrate)
{
	if (uart_buadrate) {
		buadrate = atoi(uart_buadrate);
		printf("uart_buadrate=%s\n", uart_buadrate);
		printf("buadrate=%d\n", buadrate);
	}
	else {
		buadrate = BUADRATE_DEFAULT;
		printf("UART_BUADRATE is null,use default\n");
	}
}
//气体告警阈值
void xSet_H2_threshold(const char* H2_threshold)
{
	if (H2_threshold) {
		h2_threshold = atof(H2_threshold);
		printf("H2_threshold=%s\n", H2_threshold);
		printf("h2_threshold=%f\n", h2_threshold);
	}
	else {
		h2_threshold = H2_THRESHOLD;
		printf("H2_THRESHOLD is null,use default\n");
	}
}
void xSet_CO_threshold(const char* CO_threshold)
{
	if (CO_threshold) {
		co_threshold = atof(CO_threshold);
		printf("CO_threshold=%s\n", CO_threshold);
		printf("co_threshold=%f\n", co_threshold);
	}
	else {
		co_threshold = CO_THRESHOLD;
		printf("CO_THRESHOLD is null,use default\n");
	}
}
void xSet_CO2_threshold(const char* CO2_threshold)
{
	if (CO2_threshold) {
		co2_threshold = atof(CO2_threshold);
		printf("H2_threshold=%s\n", CO2_threshold);
		printf("co2_threshold=%f\n", co2_threshold);
	}
	else {
		co2_threshold = CO2_THRESHOLD;
		printf("CO2_THRESHOLD is null,use default\n");
	}
}
void xSet_CH4_period(const char* CH4_threshold)
{
	if (CH4_threshold) {
		ch4_threshold = atof(CH4_threshold);
		printf("CH4_threshold=%s\n", CH4_threshold);
		printf("ch4_threshold=%f\n", ch4_threshold);
	}
	else {
		ch4_threshold = CH4_THRESHOLD;
		printf("CH4_THRESHOLD is null,use default\n");
	}
}
void xSet_C2H2_threshold(const char* C2H2_threshold)
{
	if (C2H2_threshold) {
		c2h2_threshold = atof(C2H2_threshold);
		printf("C2H2_threshold=%s\n", C2H2_threshold);
		printf("c2h2_threshold=%f\n", c2h2_threshold);
	}
	else {
		c2h2_threshold = C2H2_THRESHOLD;
		printf("C2H2_THRESHOLD is null,use default\n");
	}
}
void xSet_C2H4_period(const char* C2H4_threshold)
{
	if (C2H4_threshold) {
		c2h4_threshold = atof(C2H4_threshold);
		printf("C2H4_threshold=%s\n", C2H4_threshold);
		printf("c2h4_threshold=%f\n", c2h4_threshold);
	}
	else {
		c2h4_threshold = C2H4_THRESHOLD;
		printf("C2H4_THRESHOLD is null,use default\n");
	}
}
void xSet_C2H6_threshold(const char* C2H6_threshold)
{
	if (C2H6_threshold) {
		c2h6_threshold = atof(C2H6_threshold);
		printf("C2H6_threshold=%s\n", C2H6_threshold);
		printf("c2h6_threshold=%f\n", c2h6_threshold);
	}
	else {
		c2h6_threshold = C2H6_THRESHOLD;
		printf("C2H6_THRESHOLD is null,use default\n");
	}
}

void xSet_H2_alert(const char* H2_alert)
{
	if (H2_alert) {
		H2_alert_flag = atoi(H2_alert);
		printf("H2_alert=%s\n", H2_alert);
		printf("H2_alert_flag=%d\n", H2_alert_flag);
	}
	else {
		H2_alert_flag = 0;//不告警
		printf("H2_alert is null,use default\n");
	}
}

void xSet_CO_alert(const char* CO_alert)
{
	if (CO_alert) {
		CO_alert_flag = atoi(CO_alert);
		printf("CO_alert=%s\n", CO_alert);
		printf("CO_alert_flag=%d\n", CO_alert_flag);
	}
	else {
		CO_alert_flag = 0;//不告警
		printf("CO_alert is null,use default\n");
	}
}

void xSet_CO2_alert(const char* CO2_alert)
{
	if (CO2_alert) {
		CO2_alert_flag = atoi(CO2_alert);
		printf("CO2_alert=%s\n", CO2_alert);
		printf("CO2_alert_flag=%d\n", CO2_alert_flag);
	}
	else {
		CO2_alert_flag = 0;//不告警
		printf("CO2_alert is null,use default\n");
	}
}
//软件启动时继电器的默认状态 常开
void xAll_relay_normal_open()
{
	Sleep(1000 * 20);
	unsigned char rcv_buf[1024] = { 0 };
	INT res = false;
	SerialPort usb_serial0;
	char  com_name[50] = { 0 };

	res = xEnum_relay_comName(com_name);//获取继电器对应的串口名称
	if (res != true) {
		printf("xAll_relay_normal_open, not find CH340，set relay default state fail\n");
		return;
	}
	else {
		printf("find CH340 com: %s\n", com_name);
	}
	res = usb_serial0.open(com_name, buadrate, 0, 8, 1, NoFlowControl, 1);
	if (res != true) {
		cout << "open usb uart failed,continue" << endl;//考虑加错误处理
		return;
	}

	for (int i = 0; i < MAX_ALERT; i++) {
			memset(rcv_buf, 0, sizeof(rcv_buf));
			cout << "i ==" << i << endl;
			xUnsigned_char_hex_out("uart send", uart_open_cmd_arr[i], 0, 2);
			res = usb_serial0.send(uart_open_cmd_arr[i], 3);
			cout << "send byte = " << res << endl;		
			//接受单片机回复
			cout << "try recv..." << endl;
			res = usb_serial0.receive(rcv_buf, 5);
			cout << "recv byte = " << res << endl;
			if (0 != res) {
				cout << "recv msg from uart " << com_name << endl;
				xUnsigned_char_hex_out("uart recv", rcv_buf, 0, 5);
				if (0xEF == (unsigned char)rcv_buf[3]) {//如果成功，返回命令 + EF ，EF是第四个字节
					cout << "uart send succ " << com_name << endl;
				}
			}
			else {
				cout << "not recv uart msg" << endl;
			}
		Sleep(10);//每个信号数据包加点间隔
	}
	cout << "close uart" << endl;
	usb_serial0.close();
}

void alert_data_compare(ysp_modbus_regs_t ysp_data)
{
	memset(uart_signal_arr, 0, sizeof(uart_signal_arr));
	cout << "\n======================" << endl;
	if (H2_alert_flag) {
		//H2
		cout << "\n    H2 h2_threshold = " << h2_threshold << endl;
		cout << "    ysp_data.H2 curr value = " << ysp_data.H2 << endl;
		if (ExceedThreshold(ysp_data.H2, h2_threshold)) {
			//超过阈值，uart输出控制信号
			cout << "H2 over" << endl;
			cout << "H2 relay normal close" << endl;
			uart_signal_arr[H2][0] = DATA_HAS_CHANGE;//第一个byte表示那个数据需要输出信号
			uart_signal_arr[H2][1] = NORMAL_CLOSE;//第二个byte表示该数据输出什么信号
		}
		else {
			cout << "H2 not over" << endl;
			cout << "H2 relay normal open" << endl;
			uart_signal_arr[H2][0] = DATA_HAS_CHANGE;//第一个byte表示那个数据需要输出信号
			uart_signal_arr[H2][1] = NORMAL_OPEN;//第二个byte表示该数据输出什么信号
		}
	}
	if (CO_alert_flag) {
		//CO
		cout << "\n    CO co_threshold = " << co_threshold << endl;
		cout << "    ysp_data.CO curr value = " << ysp_data.CO << endl;
		if (ExceedThreshold(ysp_data.CO, co_threshold)) {
			//超过阈值，uart输出控制信号
			cout << "CO over" << endl;
			cout << "CO relay normal close" << endl;
			uart_signal_arr[CO][0] = DATA_HAS_CHANGE;//第一个byte表示那个数据需要输出信号
			uart_signal_arr[CO][1] = NORMAL_CLOSE;
		}
		else {
			//在范围内，uart输出控制信号
			cout << "CO ont over" << endl;
			cout << "CO relay normal open" << endl;
			uart_signal_arr[CO][0] = DATA_HAS_CHANGE;//第一个byte表示那个数据需要输出信号
			uart_signal_arr[CO][1] = NORMAL_OPEN;//第二个byte表示该数据输出什么信号		
		}
	}
	if (CO2_alert_flag) {
		//CO2
		cout << "\n    CO2 co2_threshold = " << co2_threshold << endl;
		cout << "    ysp_data.CO2 curr value = " << ysp_data.CO2 << endl;
		if (ExceedThreshold(ysp_data.CO2, co2_threshold)) {
			//超过阈值，uart输出控制信号
			cout << "CO2 over" << endl;
			cout << "CO2 relay normal close" << endl;
			uart_signal_arr[CO2][0] = DATA_HAS_CHANGE;//第一个byte表示那个数据需要输出信号
			uart_signal_arr[CO2][1] = NORMAL_CLOSE;//常闭
		}
		else {
			cout << "CO2 not over" << endl;
			cout << "CO2 relay normal open" << endl;
			uart_signal_arr[CO2][0] = DATA_HAS_CHANGE;//第一个byte表示那个数据需要输出信号
			uart_signal_arr[CO2][1] = NORMAL_OPEN;//常开
		}
	}
	

	cout << "\n======================" << endl;
}

DWORD WINAPI Gas_threadProc(LPVOID lp) {
	char* com = (char*)lp;
	unsigned char rcv_buf[1024] = {0};
	INT res = false;
	SerialPort usb_serial0;
	char uart_cmd[1024] = {0};
	static char last_signal_CO2 = NOT_OVER_THRESHOLD;//默认是0,表示低于阈值
	static char last_signal_H2 = NOT_OVER_THRESHOLD;//默认是0
	static char last_signal_CO = NOT_OVER_THRESHOLD;//默认是0
	ULONGLONG startTick = 0;

	char  com_name[50] = { 0 };

	//继电器默认状态为
	xAll_relay_normal_open();

	ysp_modbus_regs_t ysp_data = {0};
	//周期从数据库读气体数据，并判断和阈值比较如果超过，则控制继电器输出开关量
	while (1) {
		startTick = GetTickCount64();

		
		cout << "loop monitor period " << (monitor_period) << " mintues" << endl;
		
		Sleep(PERIOD_MONITOR(monitor_period));//周期大小分钟

		_tprintf(_T("sleep : %I64u ms\n"), GetTickCount64() - startTick);
		xGet_config_from_configFile();//just for test 

		cout << "grap gas data from database" << endl << endl;
		memset(uart_signal_arr, 0, sizeof(uart_signal_arr));
		
		if (fill_ysp_data(&ysp_data)) {
			continue;
		}

		alert_data_compare(ysp_data);
#if 0
		cout << "\n======================" << endl;
		//H2
		cout << "\n    H2 h2_threshold = " << h2_threshold << endl;
		cout << "    ysp_data.H2 curr value = " << ysp_data.H2 << endl;
		if (ExceedThreshold(ysp_data.H2, h2_threshold)) {
			//超过阈值，uart输出控制信号
			cout << "H2 over" << endl;
			cout << "H2 relay normal close" << endl;
			uart_signal_arr[H2][0] = DATA_HAS_CHANGE;//第一个byte表示那个数据需要输出信号
			uart_signal_arr[H2][1] = NORMAL_CLOSE;//第二个byte表示该数据输出什么信号
		}
		else {
			cout << "H2 not over" << endl;
			cout << "H2 relay normal open" << endl;
			uart_signal_arr[H2][0] = DATA_HAS_CHANGE;//第一个byte表示那个数据需要输出信号
			uart_signal_arr[H2][1] = NORMAL_OPEN;//第二个byte表示该数据输出什么信号
		}
		//CO
		cout << "\n    CO co_threshold = " << co_threshold << endl;
		cout << "    ysp_data.CO curr value = " << ysp_data.CO << endl;
		if (ExceedThreshold(ysp_data.CO, co_threshold)) {
			//超过阈值，uart输出控制信号
			cout << "CO over" << endl;
			cout << "CO relay normal close" << endl;
			uart_signal_arr[CO][0] = DATA_HAS_CHANGE;//第一个byte表示那个数据需要输出信号
			uart_signal_arr[CO][1] = NORMAL_CLOSE;
		}
		else {
			//在范围内，uart输出控制信号
			cout << "CO ont over" << endl;
			cout << "CO relay normal open" << endl;
			uart_signal_arr[CO][0] = DATA_HAS_CHANGE;//第一个byte表示那个数据需要输出信号
			uart_signal_arr[CO][1] = NORMAL_OPEN;//第二个byte表示该数据输出什么信号		
		}
		//CO2
		cout << "\n    CO2 co2_threshold = " << co2_threshold << endl;
		cout << "    ysp_data.CO2 curr value = " << ysp_data.CO2 << endl;
		if (ExceedThreshold(ysp_data.CO2, co2_threshold)) {
			//超过阈值，uart输出控制信号
			cout << "CO2 over" << endl;
			cout << "CO2 relay normal close" << endl;
			uart_signal_arr[CO2][0] = DATA_HAS_CHANGE;//第一个byte表示那个数据需要输出信号
			uart_signal_arr[CO2][1] = NORMAL_CLOSE;//常闭
		}
		else {
			cout << "CO2 not over" << endl;
			cout << "CO2 relay normal open" << endl;
			uart_signal_arr[CO2][0] = DATA_HAS_CHANGE;//第一个byte表示那个数据需要输出信号
			uart_signal_arr[CO2][1] = NORMAL_OPEN;//常开
		}

		cout <<"\n======================" << endl;
#endif
#if 0
		int signal_sum = 0;
		for (int i = 0; i < MAX_ALERT; i++) {
			signal_sum += uart_signal_arr[i][0];
		}

		if (0 == signal_sum) {
			cout << "no change,continue" << endl;
			continue;//说明数据范围没有变化
		}
		cout << "some gas over" << endl;
		//有数据范围发生变化，打开uart
		cout << "com number " << com << endl;
#else
		cout << "try synchronize all signal to relay"<< endl;
#endif
		
#if 1
		memset(com_name, 0, sizeof(com_name));
		res = xEnum_relay_comName(com_name);//获取继电器对应的串口名称
		if (res != true) {
			printf("not find CH340， synchronize signal fail,continue monitor\n");
			continue;
		}
		else {
			printf("find CH340 com: %s\n", com_name);
		}
#endif
		res = usb_serial0.open(com_name, buadrate, 0, 8, 1, NoFlowControl, 1);
		if (res != true) {
			cout << "open usb uart failed,continue" << endl;//考虑加错误处理
			continue;
		}
		
		for (int i = 0; i < MAX_ALERT; i++) {
			for (int j = 0; j < 2; j++) {
				memset(rcv_buf, 0, sizeof(rcv_buf));
				if (DATA_HAS_CHANGE == uart_signal_arr[i][0]) {
					
					cout << "i ==" << i << endl;
					if (NORMAL_CLOSE == uart_signal_arr[i][1]) {
						xUnsigned_char_hex_out("uart send",uart_close_cmd_arr[i], 0, 2);
						//发送指令
						res = usb_serial0.send(uart_close_cmd_arr[i], 3);
						cout << "send byte = " << res << endl;
					}
					else if (NORMAL_OPEN == uart_signal_arr[i][1]) {
						xUnsigned_char_hex_out("uart send", uart_open_cmd_arr[i],0,2);
						res = usb_serial0.send(uart_open_cmd_arr[i], 3);
						cout << "send byte = " << res << endl;
					}
			
					//接受单片机回复
					cout << "try recv..."<< endl;
					res = usb_serial0.receive(rcv_buf, 5);
					cout << "recv byte = " << res << endl;
					if (0 != res) {
						cout << "recv msg from uart "<< com_name << endl;
						xUnsigned_char_hex_out("uart recv", rcv_buf, 0, 5);
						if (0xEF == (unsigned char)rcv_buf[3]) {//如果成功，返回命令 + EF ，EF是第四个字节
							cout << "uart send succ " << com_name << endl;
							break;//succ
						}
					}
					else {
						cout << "not recv uart msg" << endl;
					}
					//try again
				}
			}

			Sleep(50);//每个信号数据包加点间隔
		}
		cout << "close uart" << endl;
		usb_serial0.close();
	}


#if 0
	while (1) {
		for (int i = 0; i < 6; i++) {
			uart_cmd[0] = 0x00;
			uart_cmd[1] = 0xF1 + i;
			uart_cmd[2] = 0xff;
			usb_serial0.send(uart_cmd, 3);
			cout << "sendt i "<< i << endl;
			usb_serial0.receive(rcv_buf, 100);
			cout << "recv msg from uart 0" << endl;
			cout << setbase(16) << rcv_buf[0] << endl;
			Sleep(2000);
		}

		for (int i = 0; i < 6; i++) {
			uart_cmd[0] = 0x00;
			uart_cmd[1] = 0x01 + i;
			uart_cmd[2] = 0xff;
			usb_serial0.send(uart_cmd, 3);
			usb_serial0.receive(rcv_buf, 100);
			cout << "recv msg from uart 0" << endl;
			cout << setbase(16) << rcv_buf[0] << endl;
			Sleep(2000);
		}
	
	}
#endif
	return 0;
}
int xGas_alert_task_init(char * uart_port)
{
	// 创建线程，返回句柄
	int a = 0;
	HANDLE h = CreateThread(NULL, 0, Gas_threadProc, uart_port, 0, 0);
	printf("start Gas monitor thread\n");
	//WaitForSingleObject(h, INFINITE);


	//CloseHandle(h);
	return 0;
}