本系统是一个基于
Qt
开发的远程控制监控系统
。采用了C/S
架构,服务端运行在X4418
实验平台上,客户端运行在与实验平台网络通畅的主机上。
本系统分为两大模块:登陆模块
与监控模块
。
服务器端能够通过外置摄像头监控,保存数据库,响应客户端的登陆,注册,截图,暂停等请求。
客户端能够远程访问服务器,在登陆后,进行截屏,暂停等操作。
- 基于Cortex-A9 Android&Linux(s4418)
- X4418实验平台
Qt5.0
以上版本
sqlite
数据库(QSql
)- 内核(课程提供)
CurrentUser
一栏显示为空。192.168.0.101:19999
(默认显示)连接到服务器。重复注册
登陆无效账户
顺利注册(test@test)
CurrentUser
显示test
。点击暂停Stop
,暂停屏幕。ScreenShot
,获取截图。Item | Description | Type |
---|---|---|
UserName | User Account[regist and log] | varchar |
Password | Password | varchar |
变量QSqlDatabase db;
数据库初始化
//open database
db = QSqlDatabase::addDatabase("QSQLITE", "QSQLITE");
db.setDatabaseName("./MyDB.db");
bool ok = db.open();
//create table
if (ok) {
QSqlQuery qsQuery = QSqlQuery(db);
QString strSqlText = QString("CREATE TABLE User ( Username VARCHAR(256),Password VARCHAR(256));");
qsQuery.prepare(strSqlText);
if(!qsQuery.exec())
{
QSqlError lastError = qsQuery.lastError();
qDebug() << lastError.driverText() << QString(QObject::tr("Create failed."));
} else {
qDebug() << "Create table user";
}
qsQuery.finish();
}
Qt += sql
设计思想:
由类MonitoeServer
来控制,数据库接口只提供增
查
服务。
INSERT INTO USER (Username, Password)
VALUES (_name, _pw)
void Regist(QString name, QString pw)
//user regist
void MonitorServer::Regist(QString name, QString pw)
{
QSqlQuery qsQuery = QSqlQuery(db);
qsQuery.prepare("INSERT INTO User (Username, Password) "
"VALUES (:name, :pw)");
qsQuery.bindValue(":name", name);
qsQuery.bindValue(":pw", pw);
if(!qsQuery.exec())
{
QSqlError lastError = qsQuery.lastError();
qDebug() << lastError.driverText() << QString(QObject::tr("Insert failed."));
}
qsQuery.finish();
}
SELECT * FROM USER
WHERE Username = _name
AND Password = _pw
bool ComfirmUser(QString name, QString pw)
//comfirm account exsists or not
bool MonitorServer::ComfirmUser(QString name, QString pw)
{
QSqlQuery qsQuery = QSqlQuery(db);
qsQuery.exec("select * from User WHERE Username = '" + name + "' AND Password = '" + pw + "'");
if(!qsQuery.exec())
{
QSqlError lastError = qsQuery.lastError();
qDebug() << lastError.driverText() << QString(QObject::tr("Query failed."));
}
if (qsQuery.next()) {
qsQuery.finish();
return true;
} else {
qsQuery.finish();
return false;
}
}
CS
模型采用
Client-Server
模型。
根据需求,将监控系统(实验平台)设置为服务器端[192.168.0.101:19999
],而用户端设置为客户端。
服务器端具有
- 用户数据库
- 监控
而客户端不保留有数据(从服务器端请求的数据除外)。
服务端能够实时监控。
客户端在登陆后能够控制客户端暂停
继续
获取截屏
客户端与服务器端[
192.168.0.101:19999
]连接后。每次交互时,客户端向服务器端发送一条请求,服务器端处理后向客户端发送一条响应。
由于过程简单,因此不设定具体形式。
采用tcp
连接。
request
response
集合
- 登录请求
request
:login-{UserName}-{Password}-end
response
(success):login-success
response
(fail: No Account):login-fail
- 注册请求
request
:regist
-{UserName}-{Password}-end
response
(success):regist-success
response
(fail: Has Account):regist-fail
- 截屏请求
request
:shot-{UserName}-end-end
response
:Image
- Send two message back, first is response, second is Image(QByteArray)
- 暂停请求
request
:stop-{UserNmae}-end-end
response
(success):stop-success
response
(fail: In Stop State):stop-fail
- 继续请求
request
:continue-{UserName}-end-end
response
(success):continue-success
response
(fail):continue-fail
为了配合
Server
使用QCamera
,使用QWidget
设计师类。
下面分为操作界面设计
操作流程
实现及关键代码
几个部分进行介绍。
由于只有两个场景,且每一个场景中的组件数目都不多,因此将所有组件放在一个页面中,通过主类的状态控制及组建的
SetVisible()
方法来控制显示。
输入服务器地址及端口号(Initial: 127.0.0.1:19999, Server: 192.168.0.101:19999),并连接到服务器。
输入账号及密码,完成登陆/注册。输入错误,返回上一页面重新输入。
通过按钮控制。(
ScreenShot
: 截屏;Stop/Continue
: 暂停/继续)
Tips:
1. Stop
按钮在点击之后会变成Continue
,再次点击恢复。
2. 点击ScreenShot
按钮后屏幕上会显示当前得到的截屏。
MonitorClient
class MonitorClient : public QWidget
{
Q_OBJECT
public:
explicit MonitorClient(QWidget *parent = 0);
~MonitorClient();
QTcpSocket *pTcpSocketClient; //socket(client)
QString name; //username
bool getPic; //recieve picture(true), other request
void SendMesg(QString strMesg); //send request to server
private:
Ui::MonitorClient *ui;
private slots:
//connect to server
void slotConnectServer();
//get response from server & deal response
void slotReadMesg();
//log in, send login request
void slotLogin();
//regist, send regist request
void slotRegist();
//return, return to the last layer
void slotReturn();
//screen shot, send screen shot request
void slotShot();
//stop/continue, send stop/ contimue request
void slotStop();
};
ui->setupUi(this);
//connect slot
this->connect(ui->pushButton_ConnectServer,SIGNAL(clicked()),this,SLOT(slotConnectServer()));
this->connect(ui->pushButton_login,SIGNAL(clicked()),this,SLOT(slotLogin()));
this->connect(ui->pushButton_regist,SIGNAL(clicked()),this,SLOT(slotRegist()));
this->connect(ui->pushButton_return,SIGNAL(clicked()),this,SLOT(slotReturn()));
this->connect(ui->pushButton_shot,SIGNAL(clicked()),this,SLOT(slotShot()));
this->connect(ui->pushButton_stop,SIGNAL(clicked()),this,SLOT(slotStop()));
//set views
getPic = false;
ui->label_warning->setText("Input the server IP and port");
ui->label_name->setText("IP:");
ui->label_pw->setText("Port:");
ui->lineEdit_name->setText("127.0.0.1");
ui->lineEdit_pw->setText("19999");
ui->splitter_log->setVisible(false);
ui->splitter_screen->setVisible(false);
ui->label_image->setVisible(false);
void slotConnectServer()
////connect to server
void MonitorClient::slotConnectServer()
{
//get IP and Port
if(ui->lineEdit_name->text().isEmpty() ||ui->lineEdit_pw->text().isEmpty())
{
//Warning
QMessageBox::warning(this,tr("Warning"),tr("Please input IP OR NetPort!"));
return;
}
//abort and reconnect
pTcpSocketClient = new QTcpSocket(this);
pTcpSocketClient->abort();
QString qStrIP = ui->lineEdit_name->text();
quint16 netport = ui->lineEdit_pw->text().toInt();
pTcpSocketClient->connectToHost(qStrIP,netport);
//bind the slot and readyRead
connect(pTcpSocketClient,SIGNAL(readyRead()),this,SLOT(slotReadMesg()));
//set visible
ui->label_warning->clear();
ui->lineEdit_name->clear();
ui->lineEdit_pw->clear();
ui->label_name->setText("UserName:");
ui->label_pw->setText("Password:");
ui->lineEdit_pw->setEchoMode(QLineEdit::Password);
ui->pushButton_ConnectServer->setVisible(false);
ui->splitter_log->setVisible(true);
}
void SendMesg(QString strMesg)
//send message to server
void MonitorClient::SendMesg(QString strMesg) //发送消息
{
pTcpSocketClient->write(strMesg.toStdString().c_str(),strlen(strMesg.toStdString().c_str()));
}
void slotLogin()
//log in, send login request
void MonitorClient::slotLogin()
{
QString command = "login";
QString name = ui->lineEdit_name->text();
QString pw = ui->lineEdit_pw->text();
QString msg = command + "-" + name + "-" + pw + "-end";
this->SendMesg(msg);
}
void slotRegist()
//regist, send regist request
void MonitorClient::slotRegist()
{
QString command = "regist";
QString name = ui->lineEdit_name->text();
QString pw = ui->lineEdit_pw->text();
QString msg = command + "-" + name + "-" + pw + "-end";
this->SendMesg(msg);
}
void slotShot()
//screen shot, send screen shot request
void MonitorClient::slotShot()
{
//need to get Image from server
this->getPic = true;
//set views
QString command = "shot";
QString name = ui->lineEdit_name->text();
QString file = ui->lineEdit_test->text();
QString msg = command + "-" + name + "-" + file + "-end";
this->SendMesg(msg);
ui->label_warning->setText("Screen Shot");
}
void slotStop()
//stop/continue, send stop/ contimue request
void MonitorClient::slotStop() {
if (ui->pushButton_stop->text() == "Stop") {
//set pushButton
ui->pushButton_stop->setText("Continue");
QString command = "stop";
QString name = ui->lineEdit_name->text();
QString msg = command + "-" + name + "-end-end";
this->SendMesg(msg);
} else {
//set pushButton
ui->pushButton_stop->setText("Stop");
QString command = "continue";
QString name = ui->lineEdit_name->text();
QString msg = command + "-" + name + "-end-end";
this->SendMesg(msg);
}
}
void slotReadMesg()
//get response from server & deal response
void MonitorClient::slotReadMesg()
{
//read the response
QByteArray qba= pTcpSocketClient->readAll();
//if it's a screen shot request
if (getPic) {
//convert QByteArray to Image
QImage *image2 = new QImage;
image2->loadFromData(qba, "PNG");
//show the Image at the label
ui->label_image->setPixmap(QPixmap::fromImage(*image2));
ui->label_image->show();
//set the getImage flag to false
getPic = false;
return;
}
//convert the request to the QString to handle
QString ss=QVariant(qba).toString();
QStringList resp = ss.split("-");
if (resp[0] == "login") {
//login response
if (resp[1] == "success") {
ui->label_warning->setText("Login success");
name = resp[2];
ui->splitter_user->setVisible(false);
ui->splitter_screen->setVisible(true);
ui->label_image->setVisible(true);
} else{
ui->label_warning->setText("Login fail");
ui->splitter_name->setVisible(false);
ui->splitter_pw->setVisible(false);
ui->splitter_log->setVisible(false);
}
} else if (resp[0] == "regist"){
//regist response
if (resp[1] == "success") {
ui->label_warning->setText("Regist success");
name = resp[2];
ui->splitter_user->setVisible(false);
ui->splitter_screen->setVisible(true);
ui->label_image->setVisible(true);
} else{
ui->label_warning->setText("Regist fail");
ui->splitter_name->setVisible(false);
ui->splitter_pw->setVisible(false);
ui->splitter_log->setVisible(false);
}
}
}
包含数据库及一个摄像头。
启动后,能够相应客户端的请求,客户端能够通过请求控制监控。
QT += multimedia
QT += multimediawidgets
class MonitorServer : public QWidget
{
Q_OBJECT
public:
explicit MonitorServer(QWidget *parent = 0);
~MonitorServer();
QTcpServer *m_pTcpServer;
QTcpSocket *pTcpSocketServer; //Server
QSqlDatabase db; //user account information database
QString user; //current user
//user regist
void Regist(QString name, QString pw);
//comfirm user exsist or not
bool ComfirmUser(QString name, QString pw);
private:
Ui::MonitorServer *ui;
//send response to client
void SendMesg(QString strMesg);
QCamera* m_pCamera; //load QCamera
QCameraViewfinder* m_pViewfinder; //randered QCamera
QCameraImageCapture* m_pImageCapture; //get QCamera current frame
private slots:
//new client connect
void slotNewConnect();
//get request from client and deal with response
void slotReadMesg();
//test pushButton
void slotTest();
};
//initial server
m_pTcpServer = new QTcpServer();
m_pTcpServer->listen(QHostAddress::Any,19999);
this->connect(m_pTcpServer,SIGNAL(newConnection()),this,SLOT(slotNewConnect()));
this->connect(ui->pushButton,SIGNAL(clicked()),this,SLOT(slotTest()));
//initial QCarema
m_pCamera = new QCamera(this);
m_pViewfinder = new QCameraViewfinder(this);
m_pImageCapture = new QCameraImageCapture(m_pCamera);
mainLayout->addWidget(m_pViewfinder);
connect(m_pImageCapture, SIGNAL(imageCaptured(int,QImage)), this, SLOT(cameraImageCaptured(int,QImage)));
m_pImageCapture->setCaptureDestination(QCameraImageCapture::CaptureToFile);
m_pCamera->setCaptureMode(QCamera::CaptureStillImage);
m_pCamera->setViewfinder(m_pViewfinder);
m_pCamera->start();
------
void slotNewConnect()
//new client connect
void MonitorServer::slotNewConnect()
{
pTcpSocketServer = m_pTcpServer->nextPendingConnection();
this->connect(pTcpSocketServer,SIGNAL(readyRead()),this,SLOT(slotReadMesg()));
}
void Regist(QString name, QString pw)
//user regist
void MonitorServer::Regist(QString name, QString pw)
{
QSqlQuery qsQuery = QSqlQuery(db);
qsQuery.prepare("INSERT INTO User (Username, Password) "
"VALUES (:name, :pw)");
qsQuery.bindValue(":name", name);
qsQuery.bindValue(":pw", pw);
if(!qsQuery.exec())
{
QSqlError lastError = qsQuery.lastError();
qDebug() << lastError.driverText() << QString(QObject::tr("Insert failed."));
}
qsQuery.finish();
}
//comfirm account exsists or not
bool MonitorServer::ComfirmUser(QString name, QString pw)
{
QSqlQuery qsQuery = QSqlQuery(db);
qsQuery.exec("select * from User WHERE Username = '" + name + "' AND Password = '" + pw + "'");
if(!qsQuery.exec())
{
QSqlError lastError = qsQuery.lastError();
qDebug() << lastError.driverText() << QString(QObject::tr("Query failed."));
}
if (qsQuery.next()) {
qsQuery.finish();
return true;
} else {
qsQuery.finish();
return false;
}
}
void cameraImageCaptured(int, QImage image)
//capture current Image & send response
void MonitorServer::cameraImageCaptured(int, QImage image)
{
QByteArray ba;
QBuffer buffer(&ba);
buffer.open(QIODevice::WriteOnly);
image.save(&buffer, "PNG");
QImage *image2 = new QImage;
image2->loadFromData(ba, "PNG");
ui->label->setPixmap(QPixmap::fromImage(*image2));
ui->label->show();
this->SendMesg(QString(ba));
}
void slotReadMesg()
//get request from client and deal with response
void MonitorServer::slotReadMesg()
{
QByteArray qba= pTcpSocketServer->readAll(); //读取
QString ss=QVariant(qba).toString();
QStringList req = ss.split("-");
if(req[0] == "login") {
qDebug() << "User Log in";
if(this->ComfirmUser(req[1], req[2])) {
qDebug() << "Yes, ok";
QString resp = "login-success-" + req[1] + "-end";
this->SendMesg(resp);
ui->label_user->setText("current user: " + req[1]);
} else{
QString resp = "login-fail-" + req[1] + "-end";
this->SendMesg(resp);
}
} else if (req[0] == "regist") {
qDebug() << "User Regist";
if(this->ComfirmUser(req[1], req[2])) {
qDebug() << "No, ok";
QString resp = "regist-fail-" + req[1] + "-end";
this->SendMesg(resp);
} else{
this->Regist(req[1], req[2]);
ui->label_user->setText("current user: " + req[1]);
QString resp = "regist-success-" + req[1] + "-end";
this->SendMesg(resp);
}
} else if(req[0] == "shot") {
this->m_pImageCapture->capture();
} else if (req[0] == "stop") {
ui->label_user->setText("current user: " + this->user + " STOP");
this->m_pCamera->stop();
} else {
ui->label_user->setText("current user: " + this->user);
this->m_pCamera->start();
}
}