You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

606 lines
18 KiB
C++

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

#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 CH340set 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;
}