本文适用于pc based的测控系统的上位机,定义了一套报警规则。
由5个部分组成:自定义4布尔类、在全局文件定义工位错误结构体和结构体变量,其它地方给此变量的当前值成员赋值,报警线程类、数据库保存类、弹框类。
1.自定义4布尔类
本类实现了上升沿和下降沿函数,得到信号的变化那1次。
(1)头文件(文件名:four_bl.h)
#ifndef FOUR_BL_H
#define FOUR_BL_H
//#include <QObject>
class Four_bl
{
//Q_OBJECT
public:
bool current_Value=false;//当前值
private:
bool history_Value=false;//历史值
public:
Four_bl();
bool Is_raise_edge();//上升沿
bool Is_fall_edge();//下降沿
void Refresh_history_Value();
bool Get_history_Value();
};
#endif // FOUR_BL_H
(2)cpp文件(文件名:four_bl.cpp)
#include "four_bl.h"
Four_bl::Four_bl() {}
bool Four_bl::Is_raise_edge() //上升沿
{
return (current_Value && !history_Value);
}
bool Four_bl::Is_fall_edge() //下降沿
{
return (!current_Value && history_Value);
}
void Four_bl::Refresh_history_Value() //刷新历史值
{
history_Value=current_Value;
}
bool Four_bl::Get_history_Value()//得到历史值
{
return history_Value;
}
2.在全局文件中
(1) 头文件中添加(文件名:global_def.h)
struct staion_error
{
Four_bl motor_error;//马达故障
Four_bl negative_limit;//负限位
Four_bl positive_limit;//正限位
//...有多少就定义多少
};
extern staion_error global_staion_error_array[3];//工位故障数组,你有多少个工位就写多少长度
(2) cpp文件(文件名:global_def.cpp)
staion_error global_staion_error_array[3];//与头文件中那个数组长度要一样
3.给此变量的当前值成员赋值
for(int i=0;i<3;i++)
{
global_staion_error_array[i].motor_error.current_Value= ;//补上右边
global_staion_error_array[i].positive_limit.current_Value= ;//补上右边
global_staion_error_array[i].negative_limit.current_Value= ;//补上右边
}
4.报警线程类
(1)头文件(文件名:alarm_thread.h)
#ifndef ALARM_THREAD_H
#define ALARM_THREAD_H
#include <QObject>
#include <QThread>
#include <QDebug>
#include <QString>
//#include <QCoreApplication>
#include "global_def.h"
#include <QMutexLocker>
#include <datapoolpage.h>
class Alarm_Thread : public QThread
{
Q_OBJECT
private:
bool m_paused=true; //暂停
bool m_stop=false; //停止线程run()
long Seq=0;//序次
protected:
void run(); //线程的事件循环
public:
void Begin(); //开始
void Pause(); //暂停
void stopThread(); //结束线程run()
explicit Alarm_Thread(QObject *parent = nullptr);
signals:
private slots:
void ChangeState(QString cmd);
};
#endif // ALARM_THREAD_H
(2) cpp文件(文件名:alarm_thread.cpp)
#include "alarm_thread.h"
Alarm_Thread::Alarm_Thread(QObject *parent)
: QThread{parent}
{}
void Alarm_Thread::run() //线程的事件循环
{ // qDebug()<<"void Alarm_Thread::run() ";
while(!m_stop) //循环主体
{
//QElapsedTimer time_m;
//time_m.start();
QThread::msleep(2000);
if (!m_paused)
{
//qDebug()<<"void Alarm_Thread::run()-while loop-- ";
//return;
for(int i=0;i<3;i++)
{
if(global_staion_error_array[i].motor_error.Is_raise_edge())//如果是上升沿
{
//DataPoolPage::insert_alarm(i+1,"",1);//插入报警信息到数据库的
}
if(global_staion_error_array[i].motor_error.Is_fall_edge())
{ QString st_name_array[]={"","工位1","工位2","工位3"};
//DataPoolPage::update_alarm(st_name_array[i+1],1);//更新数据库的
qDebug()<<"--------------------------------";
qDebug()<<st_name_array[i+1];
}
global_staion_error_array[i].motor_error.Refresh_history_Value();
//这行要在上升沿处理和下降沿处理以后
//----------------------------------------------------------------------
if(global_staion_error_array[i].negative_limit.Is_raise_edge())
{
//DataPoolPage::insert_alarm(i+1,"",2);//插入数据库的
}
if(global_staion_error_array[i].negative_limit.Is_fall_edge())
{ QString st_name_array[]={"","工位1","工位2","工位3"};
//DataPoolPage::update_alarm(st_name_array[i+1],2);//更新数据库的
}
global_staion_error_array[i].negative_limit.Refresh_history_Value();
//------------------------------------------------------------------------
if(global_staion_error_array[i].positive_limit.Is_raise_edge())
{
//DataPoolPage::insert_alarm(i+1,"",3);//插入数据库的
}
if(global_staion_error_array[i].positive_limit.Is_fall_edge())
{ QString st_name_array[]={"","工位1","工位2","工位3"};
// DataPoolPage::update_alarm(st_name_array[i+1],3);//更新数据库的
}
global_staion_error_array[i].positive_limit.Refresh_history_Value();
if(global_staion_error_array[i].no_on_error.Is_raise_edge())
{
//DataPoolPage::insert_alarm(i+1,"",4);//插入数据库的
}
//..继续添加你的
}
else
{
//qDebug()<<"void Alarm_Thread::run()-while loop--pause ";
QThread::msleep(800);
}
QThread::msleep(2000);
}
}
void Alarm_Thread::Begin() //开始
{
m_paused=false;
}
void Alarm_Thread::Pause() //暂停
{
m_paused=true;
}
void Alarm_Thread::stopThread() //结束线程run()
{
m_stop=true;
}
void Alarm_Thread::ChangeState(QString cmd)
{
if(cmd=="begin")
{
Begin();
}
else if(cmd=="pause")
{
Pause();
}
}
5. 数据库和写入数据库的类
5.1建立数据库和表
5.2 写入数据库的类
(1)头文件(文件名:datapoolpage.h)
#ifndef DATAPOOLPAGE_H
#define DATAPOOLPAGE_H
#include <QWidget>
#include <QSqlDatabase>
#include <QSqlError>
#include <QSqlQuery>
#include <QElapsedTimer>
#include <QDateTime>
#include <iostream>
#include <QMutexLocker>
#include "global_def.h"
namespace Ui {
class DataPoolPage;
}
class DataPoolPage: public QWidget
{
Q_OBJECT
public:
explicit DataPoolPage(QWidget *parent = nullptr);
~DataPoolPage();
//QSqlDatabase database;
void static insert_alarm(QString st,QString info1,QString info2,QDateTime dt,QString status_,int num);
void static insert_alarm(int st_num,QString info2,int num);
void static update_alarm(QString st,int num);
private slots:
private:
Ui::DataPoolPage *ui;
int seq=1;
};
#endif // DATAPOOLPAGE_H
(2)cpp文件(文件名:datapoolpage.cpp)
#include "datapoolpage.h"
#include "ui_datapoolpage.h"
DataPoolPage::DataPoolPage(QWidget *parent)
: QWidget(parent)
, ui(new Ui::DataPoolPage)
{
ui->setupUi(this);
//db = QSqlDatabase::addDatabase("QMYSQL");
}
DataPoolPage::~DataPoolPage()
{
delete ui;
}
void DataPoolPage::insert_alarm(QString st,QString info1,QString info2,QDateTime dt,QString status_,int num)
{ qDebug()<<"-insert_alarm2-----"<<st;
//qDebug()<<QSqlDatabase::drivers();
//QMutexLocker locker(&g_mutx_db);
if(QSqlDatabase::contains("MySQLConnection1"))
QSqlDatabase::removeDatabase("MySQLConnection1");
QSqlDatabase db = QSqlDatabase::addDatabase("QMYSQL", "MySQLConnection1");
db.setHostName("127.0.0.1");
db.setPort(3306);
db.setDatabaseName("deviceinfodb");//你自己的数据库名称
db.setUserName("root");
db.setPassword("123456");
if (!db.open()) {
qDebug()<<"不能连接"<<"connect to mysql error"<<db.lastError().text();
db.close();
return ;
}
else
{
qDebug()<<"数据库连接成功";
}
QDateTime now = QDateTime::currentDateTime();
QSqlQuery query(db);
query.prepare("INSERT INTO current_alarms (workstation, description, description2,start_time, status,code) VALUES (:value0,:value1, :value2, :value3, :value4, :value5)");
query.bindValue(":value0",st );
query.bindValue(":value1", info1);
query.bindValue(":value2", info2);
query.bindValue(":value3", dt);
query.bindValue(":value4", status_);
query.bindValue(":value5", num);
//query.bindValue(":value4", "active");
if (!query.exec())
{
qDebug() << "Failed to insert data. Error: " << query.lastError().text();
db.close();
return ;
}
qDebug() << "Data inserted successfully";
db.close();
}
void DataPoolPage::update_alarm(QString st,int num)
{
//UPDATE `deviceinfodb`.`current_alarms` SET `status` = 'active', `resolved_time` = now() , `code` = 00000000001 WHERE `code`=1 and `status`='active' ;
qDebug()<<"void DataPoolPage::update_alarm(QString st,int num)";
//qDebug()<<QSqlDatabase::drivers();
//return;
QMutexLocker locker(&g_mutx_db);
//QSqlDatabase db= QSqlDatabase::addDatabase("QMYSQL");
//QSqlDatabase db = QSqlDatabase::addDatabase("QMYSQL", "MySQLConnection");
if(QSqlDatabase::contains("MySQLConnection2"))
QSqlDatabase::removeDatabase("MySQLConnection2");
QSqlDatabase db = QSqlDatabase::addDatabase("QMYSQL", "MySQLConnection2");
db.setHostName("127.0.0.1");
db.setPort(3306);
db.setDatabaseName("deviceinfodb");//你自己的数据库名称
db.setUserName("root");
db.setPassword("123456");
if (!db.open()) {
qDebug()<<"不能连接"<<"connect to mysql error"<<db.lastError().text();
db.close();
return ;
}
else
{
qDebug()<<"数据库连接成功";
}
QDateTime now = QDateTime::currentDateTime();
QSqlQuery query(db);
query.prepare("UPDATE current_alarms SET status = 'resolved', resolved_time = now() WHERE workstation =:value0 and code=:value1 and status='active' ");
query.bindValue(":value0",st );
query.bindValue(":value1",num );
//query.bindValue(":value4", "active");
if (!query.exec())
{
qDebug() << "Failed to insert data. Error: " << query.lastError().text();
db.close();
return ;
}
qDebug() << "Data update successfully";
db.close();
}
//说明,弹框类,在下篇文章中描述