項目背景:
在本次“新冠疫情”的衝擊下,小區需要監控人員體溫,現新進了一批可以採集人體體溫的智能體溫計,但是小區有三個門:正門,側門,後門,每個門都會有人員流動,物業希望能夠在監控室查看相關人員的體溫,可以做匹配記錄。
項目需求:
(1)每個智能體溫計都能採集體溫數據並自動上傳該數據到監控平臺。
(2)監控平臺可以實時查看各門,各人員的體溫。
(3)對於出現異常體溫(超過37.3°C)監控平臺會發出報警。
項目開發環境:
(1)QT 5.14.2。
(2)SSokit網絡調試助手。
技術支持:
(1)C語言。
(2)C++。
(3)QT界面開發。
(4)TCP協議。
:具體的項目流程與實現,我用腦圖的方式展示給大家。
TCP客戶端核心代碼:
/*******************************************************
*
* Function name :makeTemp
* Description :產生一個16位的數據:高8位整數+低8位小數
* Parameter :NULL
* Return :NULL
*
**********************************************************/
short makeTemp()
{
// 配置隨機種子:根據系統的節拍取
srand(clock());
short temp = 0;
char high = 0;
char low = 0;
while(1)
{
// 以100ms的時間間隔
usleep(100 * 1000);
// 正常體溫範圍:34-43
// 體溫整數部分隨機數產生
high = 34 + rand() % 9;
// 體溫小數部分隨機數產生
low = rand() % 100;
// 將產生的數值傳遞給temp中:位運算處理
temp = high;
temp = temp << 8;
// 最終產生的模擬體溫數值
temp += low;
gTemp = temp;
}
}
// 全局變量:存儲產生的體溫數據
short gTemp;
int main(int argc, char *argv[])
{
// 開啓多線程:將數據的產生,放在線程中
QThread::create([](){
makeTemp();
})->start();
// 連接到TCP服務器端
QTcpSocket *client = new QTcpSocket;
QHostAddress address("127.0.0.1");
client->connectToHost(address,8888);
if(client->waitForConnected())
{
// 打印對方地址和端口
qDebug() << client->peerAddress();
qDebug() << client->peerPort();
// 打印自己的地址和端口
qDebug() << client->localAddress();
qDebug() << client->localPort();
// 數據循環發送TCP服務器端
while(1)
{
// 模擬人的流動 隨機延時
sleep(1 + rand()% 9);
// write的用法 char *的地址 數據長度(字節)
client->write((char *)&gTemp,2);
client->flush();
}
}
return 0;
}
TCP客戶端數據發送驗證:
TCP服務器核心代碼:
/*******************************************************
*
* Function name :createChart
* Description :配置主顯示界面
* Parameter :NULL
* Return :NULL
*
**********************************************************/
void MainWidget::createChart()
{
// 配置基礎的圖表數據
mainChart = new QChart();
dotSeries = new QScatterSeries;
alertLineSeries = new QLineSeries;
connectLineSeries = new QLineSeries;
// X Y 座標系
QValueAxis *axisX = new QValueAxis;
QValueAxis *axisY = new QValueAxis;
// 數值範圍
axisX->setRange(0,60);
axisX->setLabelFormat("%.2f");
// 是否顯示錶格分割虛線
axisX->setGridLineVisible(true);
// 分割的格子數
axisX->setTickCount(7);
// 最小分割
axisX->setMinorTickCount(1);
// 座標代表的含義標題
axisX->setTitleText("時間");
axisY->setRange(34,43);
axisY->setLabelFormat("%.2f");
axisY->setGridLineVisible(true);
axisY->setGridLineColor(Qt::gray);
axisY->setTickCount(10);
axisY->setTitleText("體溫");
// 座標軸的位置
mainChart->addAxis(axisX,Qt::AlignBottom);
mainChart->addAxis(axisY,Qt::AlignLeft);
// 數據點,警戒線,連接線的層級關係
mainChart->addSeries(alertLineSeries);
mainChart->addSeries(connectLineSeries);
mainChart->addSeries(dotSeries);
// 隱藏圖例
mainChart->legend()->hide();
// 需要將座標系和數值範圍綁定在一起,否則顯示的數據不正確
// 必須是在將圖類型添加到圖表上之後
dotSeries->attachAxis(axisX);
dotSeries->attachAxis(axisY);
alertLineSeries->attachAxis(axisX);
alertLineSeries->attachAxis(axisY);
connectLineSeries->attachAxis(axisX);
connectLineSeries->attachAxis(axisY);
// 設置警戒線:顏色,粗細,位置
//alertLineSeries->setColor(QColor("red"));
alertLineSeries->setPen(QPen(Qt::red,3,Qt::DashLine,Qt::RoundCap,Qt::RoundJoin));
alertLineSeries->append(0,37.3);
alertLineSeries->append(60,37.3);
// 設置連接線:顏色,粗細,位置
connectLineSeries->setPen(QPen(Qt::blue,1.5,Qt::SolidLine,Qt::RoundCap,Qt::RoundJoin));
}
// 創建server,監聽端口和地址
bool MainWidget::startServer()
{
server = new QTcpServer();
return server->listen(QHostAddress("127.0.0.1"),8888);
}
void MainWidget::newConnectionAccept()
{
// 定義一個刷新圖表的時間
qreal passMinute = QTime::currentTime().minute();
qDebug() << "新連接已接入";
// 獲取當前的傳輸套接字 可以進行數據的發送和接收
dataSocket = server->nextPendingConnection();
dataSocket->write("HELLO");
// 客服端是否有新的數據發送?
// 有-> 觸發readyRead信號
// 可以對發送的數據進行處理
connect(dataSocket,&QTcpSocket::readyRead,[=]()mutable{
// 按照高8位和低8位數據轉換成真正的溫度數據
short temp = 0;
dataSocket->read((char *)&temp,2);
short t = temp >> 8;
float realTemp = t + (temp & 0x00ff) / 100.00;
qDebug() << realTemp;
// 每隔一分鐘刷新一次圖表
if( passMinute != QTime::currentTime().minute() )
{
dotSeries->clear();
connectLineSeries->clear();
passMinute = QTime::currentTime().minute();
}
dotSeries->append(QTime::currentTime().second(),realTemp);
connectLineSeries->append(QTime::currentTime().second(),realTemp);
QString tt("當前溫度爲:");
tt += QString("%1").arg(realTemp);
currentTempLabel->setText(tt);
numberDisplay->display(realTemp);
// 當體溫數值超過 37.3 就報警
if(realTemp > 37.3)
{
alertPlayer->play();
}
});
}