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++

12 months ago
#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 :
usbCH340microMCU
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;
}