#include "windows.h" #include "gas_monitor.h" #include "SerialPort.h" #include "database/database.h" #include #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; }