【博客7】缤果Qt串口蓝牙调试助手V1.0(初级篇)

超级好用的Qt5串口蓝牙调试助手 

备注: 此蓝牙为SPP蓝牙串口,搜索到蓝牙后,在蓝牙列表中双击对应的蓝牙名即可进行连接

蓝牙串口服务UUID为00001101-0000-1000-8000-00805F9B34FB
如果下位机蓝牙设备不是默认的,可在项目中connectBLE函数修改自己私有的UUID
static const QLatin1String serviceUuid("00001101-0000-1000-8000-00805F9B34FB");

开发工具: qt-opensource-windows-x86-5.14.2  (编程语言C++)

目录

前言

一、软件概要:

二、软件界面:

 1.App动态演示

  ---- ♠ ----

 2.其他扩展App展示

三、mainwindow.cpp源码

四、获取 >> 源码以及Git记录:

总结


前言

串口蓝牙调试助手支持常用的50bps - 10Mbps波特率,能设置校验、数据位和停止位,能以ASCII码或十六进制接收或发送任何数据或字符,可以任意设定自动发送周期,并能将接收数据实时保存成文本文件,能发送任意大小的数据或字符。支持蓝牙功能 !

备注: QT串口蓝牙调试助手(初级篇)是从缤果串口网络蓝牙调试助手(高级篇)分离出来的简单应用


英文名:Serial_Bluetooth_Debug_Assistant_V1.0
支持:常用的50bps ~ 10Mbps波特率
类型:串口蓝牙调试助手
软件大小:12M
软件版本:V1.0
软件下载&更新:百度网盘链接_提取码 6666

一、软件概要:

一款强大而稳定的Qt串口升级工具,支持常用的110-921600bps波特率及自定义波特率,波特率最高可支持8000000(串口硬件有关),可适应于非标准波特率。支持动态修改串口和波特率,历史发送以及实时保存日志。

二、软件界面:

 1.App动态演示

 

 2.其他扩展App展示

​  

三、mainwindow.cpp源码

#include "mainwindow.h"
#include "ui_mainwindow.h"

#if defined __Serial__ || defined __Bluetooth__
CommProType_Enum CommProType = Serial_Comm;
#endif

//Qt5.14.2(MinGW 7.3.0 64-bit) 区分32bit和64bit工程 ; 切换目录命令 cd /d 目录
//打包命令: windeployqt 项目名.exe  程序打包:Enigma Virtual Box 注意: 打包别压缩,否则打开exe文件会久一些
MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    QString WindowTitle = "Serial Bluetooth Debug Assistant V1.0";
    setWindowTitle(WindowTitle);

    #ifdef __Serial__

    //连接信号和槽
    StatusBarInit();
    TimerInit();
    NewFile();
    connect(&serial, SIGNAL(readyRead()), this, SLOT(serialPort_readyRead()));

    //波特率默认选择下拉:921600
    ui->baudrateBox->setCurrentIndex(21);
    on_searchButton_clicked();
    LoadSerialPortConfigParameters();

    #endif
}

MainWindow::~MainWindow()
{
    delete ui;
}


#ifdef __Serial__

void MainWindow::NewFile()
{
    //新建文件夹
    QDir *dir = new QDir;

    bool exist = dir->exists(NewFolder_SerialPort_Config);

    if(!exist)
    {
        //qDebug() << "new file";
        dir->mkdir(NewFolder_SerialPort_Config);
    }
    else
    {
        //qDebug() << "file exist";
    }

    exist = dir->exists(NewFolder_SerialPort_Log);

    if(!exist)
    {
        dir->mkdir(NewFolder_SerialPort_Log);
    }
}

void MainWindow::LoadSerialPortConfigParameters()
{
    //-------------------------------------------------------------------------------------------------------------
    //读取ini文件
    //com配置
    QSettings *configIniRead = new QSettings(FileName_SerialPort_Config_ini_Path, QSettings::IniFormat);
    configIniRead->setIniCodec(QTextCodec::codecForName("GB18030"));

    //将读取到的ini文件保存在QString中,先取值,然后通过toString()函数转换成QString类型
    int portNameIndex = configIniRead->value("MainWindow_SerialComPara/portNameIndex").toInt();
    int baudRateIndex = configIniRead->value("MainWindow_SerialComPara/baudRateIndex").toInt();
    int dataBitsIndex = configIniRead->value("MainWindow_SerialComPara/dataBitsIndex").toInt();
    int ParityIndex = configIniRead->value("MainWindow_SerialComPara/ParityIndex").toInt();
    int stopBitsIndex = configIniRead->value("MainWindow_SerialComPara/stopBitsIndex").toInt();
    int flowControlIndex = configIniRead->value("MainWindow_SerialComPara/flowControlIndex").toInt();
    customBaudRate = configIniRead->value("MainWindow_SerialComPara/customBaudRate").toInt();
    if(customBaudRate!=0) ui->baudrateBox->setItemText(0,QString::number(customBaudRate));

    //TRACE_2(portNameIndex,SerialPortNum);
    if(portNameIndex >= SerialPortNum) portNameIndex = 0; //修复串口减少时,串口软件打不开的问题

    ui->portNameBox->setCurrentIndex(portNameIndex);
    ui->baudrateBox->setCurrentIndex(baudRateIndex);
    ui->dataBitsBox->setCurrentIndex(dataBitsIndex);
    ui->ParityBox->setCurrentIndex(ParityIndex);
    ui->stopBitsBox->setCurrentIndex(stopBitsIndex);
    ui->flowControlBox->setCurrentIndex(flowControlIndex);

    //默认
    if(0==baudRateIndex && 0==dataBitsIndex)
    {
        ui->baudrateBox->setCurrentIndex(6);
        ui->dataBitsBox->setCurrentIndex(3);
    }

    //接收设置
    int hexReceive = configIniRead->value("MainWindow_SerialReceivePara/hexReceive").toInt();
    if(hexReceive) ui->checkBox_hexReceive->setChecked(1);
    else ui->checkBox_hexReceive->setChecked(0);

    #if 0
    int AutoLineBreak = configIniRead->value("MainWindow_SerialReceivePara/AutoLineBreak").toInt();
    if(AutoLineBreak) ui->checkBox_AutoLineBreak->setChecked(1);
    else ui->checkBox_AutoLineBreak->setChecked(0);
    //ui->checkBox_AutoLineBreak->setChecked(1); //默认1

    int displaySend = configIniRead->value("MainWindow_SerialReceivePara/displaySend").toInt();
    if(displaySend) ui->checkBox_displaySend->setChecked(1);
    else ui->checkBox_displaySend->setChecked(0);

    int displayTime = configIniRead->value("MainWindow_SerialReceivePara/displayTime").toInt();
    if(displayTime) ui->checkBox_displayTime->setChecked(1);
    else ui->checkBox_displayTime->setChecked(0);
    #endif

    //发送设置
    int hexSend = configIniRead->value("MainWindow_SerialSendPara/hexSend").toInt();
    if(hexSend) ui->checkBox_hexSend->setChecked(1);
    else ui->checkBox_hexSend->setChecked(0);

    int Send_CR_LF = configIniRead->value("MainWindow_SerialSendPara/Send_CR_LF").toInt();
    if(Send_CR_LF) ui->checkBox_CR_LF->setChecked(1);
    else ui->checkBox_CR_LF->setChecked(0);

    if(customBaudRate!=0) ui->baudrateBox->setItemText(0,QString::number(customBaudRate)); //加载语言后会修改为Custom

    //读取完成后删除指针
    delete configIniRead;

    //-------------------------------------------------------------------------------------------------------------

    //历史发送数据读取
    //读取ini文件
    QSettings *SendHistoryDataIniRead = new QSettings(FileName_SerialPort_SendHistoryData_ini_Path, QSettings::IniFormat);
    SendHistoryDataIniRead->setIniCodec(QTextCodec::codecForName("GB18030"));

    QString SendText = SendHistoryDataIniRead->value("MainWindow_SerialSendData/SendText").toString();
    ui->sendTextEdit->setText(SendText);

    int count = SendHistoryDataIniRead->value("MainWindow_SerialSendHistoryData/ItemTotalNum").toInt();
    //qDebug() << "count:" << count;

    if(count)
    {
        ui->comboBox_sendHistory->clear();

        for(int i=0; i<count; i++)
        {
            QString ItemNum = "MainWindow_SerialSendHistoryData/";
            ItemNum += QString("%1").arg(i,3,10,QLatin1Char('0'));
            QString dataStr = SendHistoryDataIniRead->value(ItemNum).toString();
            ui->comboBox_sendHistory->addItem(dataStr);
        }
    }
    //读取完成后删除指针
    delete SendHistoryDataIniRead;
}

void MainWindow::SaveSerialPortConfigParameters()
{
    //*************************************************************************************************************
    //Qt中使用QSettings类读写ini文件
    //QSettings构造函数的第一个参数是ini文件的路径,第二个参数表示针对ini文件,第三个参数可以缺省
    QSettings *configIniWrite = new QSettings(FileName_SerialPort_Config_ini_Path, QSettings::IniFormat);
    configIniWrite->setIniCodec(QTextCodec::codecForName("GB18030"));

    //向ini文件的第二个节写入内容,MainWindow 节下的第5个参数
    if(ui->baudrateBox->currentIndex()==0 && ui->baudrateBox->currentText()!="Custom")
    {
       configIniWrite->setValue("MainWindow_SerialComPara/customBaudRate", ui->baudrateBox->currentText()); //如果是字符,读出来是0
    }

    //------------------------------------------------------------------------------------------------------
    configIniWrite->setValue("MainWindow_SerialComPara/portNameIndex", ui->portNameBox->currentIndex()); //向ini文件的第一个节写入内容,COM 节下的第一个参数
    configIniWrite->setValue("MainWindow_SerialComPara/baudRateIndex", ui->baudrateBox->currentIndex()); //向ini文件的第一个节写入内容,COM 节下的第二个参数
    configIniWrite->setValue("MainWindow_SerialComPara/dataBitsIndex", ui->dataBitsBox->currentIndex());
    configIniWrite->setValue("MainWindow_SerialComPara/ParityIndex", ui->ParityBox->currentIndex());
    configIniWrite->setValue("MainWindow_SerialComPara/stopBitsIndex", ui->stopBitsBox->currentIndex());
    configIniWrite->setValue("MainWindow_SerialComPara/flowControlIndex", ui->flowControlBox->currentIndex());


    //------------------------------------------------------------------------------------------------------
    //向ini文件的第3个节写入内容,MainWindow 节下的第1个参数
    if(ui->checkBox_hexReceive->isChecked()) configIniWrite->setValue("MainWindow_SerialReceivePara/hexReceive", 1);
    else configIniWrite->setValue("MainWindow_SerialReceivePara/hexReceive", 0);

    //向ini文件的第3个节写入内容,MainWindow 节下的第1个参数
    if(ui->checkBox_AutoLineBreak->isChecked()) configIniWrite->setValue("MainWindow_SerialReceivePara/AutoLineBreak", 1);
    else configIniWrite->setValue("MainWindow_SerialReceivePara/AutoLineBreak", 0);

    //向ini文件的第3个节写入内容,MainWindow 节下的第1个参数
    if(ui->checkBox_displaySend->isChecked()) configIniWrite->setValue("MainWindow_SerialReceivePara/displaySend", 1);
    else configIniWrite->setValue("MainWindow_SerialReceivePara/displaySend", 0);

    //向ini文件的第3个节写入内容,MainWindow 节下的第1个参数
    if(ui->checkBox_displayTime->isChecked()) configIniWrite->setValue("MainWindow_SerialReceivePara/displayTime", 1);
    else configIniWrite->setValue("MainWindow_SerialReceivePara/displayTime", 0);

    //------------------------------------------------------------------------------------------------------
    //向ini文件的第3个节写入内容,MainWindow 节下的第1个参数
    if(ui->checkBox_hexSend->isChecked()) configIniWrite->setValue("MainWindow_SerialSendPara/hexSend", 1);
    else configIniWrite->setValue("MainWindow_SerialSendPara/hexSend", 0);

    //向ini文件的第3个节写入内容,MainWindow 节下的第1个参数
    if(ui->checkBox_CR_LF->isChecked()) configIniWrite->setValue("MainWindow_SerialSendPara/Send_CR_LF", 1);
    else configIniWrite->setValue("MainWindow_SerialSendPara/Send_CR_LF", 0);


    //写入完成后删除指针
    delete configIniWrite;

    //*************************************************************************************************************

    //Qt中使用QSettings类读写ini文件
    //QSettings构造函数的第一个参数是ini文件的路径,第二个参数表示针对ini文件,第三个参数可以缺省
    QSettings *SendHistoryDataIniWrite = new QSettings(FileName_SerialPort_SendHistoryData_ini_Path, QSettings::IniFormat);
    //向ini文件中写入内容,setValue函数的两个参数是键值对

    //历史发送数据保存
    SendHistoryDataIniWrite->setIniCodec(QTextCodec::codecForName("GB18030")); //中文保存

    QString SendText = ui->sendTextEdit->toPlainText();
    SendHistoryDataIniWrite->setValue("MainWindow_SerialSendData/SendText", SendText);

    int count = ui->comboBox_sendHistory->count();
    SendHistoryDataIniWrite->setValue("MainWindow_SerialSendHistoryData/ItemTotalNum", count);

    for(int i=0; i<count; i++)
    {
        QString StrItem = ui->comboBox_sendHistory->itemText(i);
        //QString Utf8_StrItem = QString::fromLocal8Bit(StrItem.toLatin1().constData()); //生成UTF-8编码字符串

        QString ItemNum = "MainWindow_SerialSendHistoryData/";
        ItemNum += QString("%1").arg(i,3,10,QLatin1Char('0'));

        SendHistoryDataIniWrite->setValue(ItemNum, StrItem);
    }

    //写入完成后删除指针
    delete SendHistoryDataIniWrite;
}


//----------------------------------------串口----------------------------------------
void MainWindow::StatusBarInit()
{
    statusBarLabelSerial = new QLabel(this); //新建一个标签
    statusBarLabelBluetooth = new QLabel(this); //新建一个标签
    statusBarLabelTx = new QLabel(this); //新建一个标签
    statusBarLabelRx = new QLabel(this); //新建一个标签

    //状态栏显示打开关闭COM信息
    QString StatusInfo = " ";
    StatusInfo += "COM Ready!";
    statusBarLabelSerial->setStyleSheet("color:black");
    statusBarLabelSerial->setText(StatusInfo); //设置标签的名字

    QString BtStatusInfo = " ";
    BtStatusInfo += "Bluetooth Ready!";
    statusBarLabelBluetooth->setStyleSheet("color:blue");
    statusBarLabelBluetooth->setText(BtStatusInfo); //设置标签的名字

    statusBarLabelRx->setText("Rx: 0 Bytes"); //设置标签的名字
    statusBarLabelTx->setText("Tx: 0 Bytes"); //设置标签的名字


    statusBarLabelSerial->setFixedWidth(260);
    statusBarLabelBluetooth->setFixedWidth(260);
    statusBarLabelTx->setFixedWidth(150);
    statusBarLabelRx->setFixedWidth(200);

    ui->statusBar->addWidget(statusBarLabelSerial);//将标签添加到状态栏
    ui->statusBar->addWidget(statusBarLabelBluetooth);//将标签添加到状态栏
    ui->statusBar->addWidget(statusBarLabelRx);//将标签添加到状态栏
    ui->statusBar->addWidget(statusBarLabelTx);//将标签添加到状态栏
}

void MainWindow::TimerInit()
{
    //自动重发
    fTimer = new QTimer(this);
    fTimer->stop();

    AutoSendTimeMs = ui->spinBox_AutoSendTime->text().toInt();
    fTimer->setInterval (AutoSendTimeMs) ;//设置定时周期,单位:毫秒
    connect(fTimer,SIGNAL(timeout()),this,SLOT(slot_timer_timeout()));
}

void MainWindow::slot_timer_timeout()
{
    //定时器中断响
    //QTime curTime = QTime::currentTime(); //获取当前时间
    //qDebug() << curTime.second(); //显示s

    //动态变化时修改定时周期
    static int CurAutoSendTimeMs = AutoSendTimeMs;

    if(AutoSendTimeMs != CurAutoSendTimeMs)
    {
        //qDebug() << AutoSendTimeMs;
        fTimer->setInterval (AutoSendTimeMs) ;//设置定时周期,单位:毫秒
    }

    CurAutoSendTimeMs = AutoSendTimeMs;

    if(CommProType == Serial_Comm) on_sendButton_clicked(); //第2~n次...

    #ifdef __Bluetooth__
    else on_sendButton_bt_clicked();
    #endif
}

void MainWindow::on_spinBox_AutoSendTime_valueChanged(int arg1)
{
    AutoSendTimeMs = arg1;
}

void MainWindow::on_searchButton_clicked()
{
    ui->portNameBox->clear();
    SerialPortNum = 0;

    //通过QSerialPortInfo查找可用串口
    foreach(const QSerialPortInfo &info, QSerialPortInfo::availablePorts())
    {
        SerialPortNum++;
        ui->portNameBox->addItem(info.portName());
    }

    if(SerialPortNum > 0)
    {
        ui->portNameBox->addItem("Refresh Port"); //刷新串口

        if(refresh_serialport_flag && SerialPortNum > 1)
        {
            ui->portNameBox->setCurrentIndex(SerialPortNum-1); //显示刷新后新增的最后一个COM口
        }
        else
        {
            ui->portNameBox->setCurrentIndex(0); //显示第一个COM
        }

        //TRACE_1(SerialPortNum);
    }
    else
    {
        refresh_serialport_null_flag = true;
        ui->portNameBox->addItem("Refresh Port"); //刷新串口
        ui->portNameBox->setCurrentIndex(0); //显示第一个COM
    }
}

void MainWindow::on_portNameBox_activated(int index)
{
    Q_UNUSED(index);
    //qDebug() << "on_portNameBox_activated index:" << index;
    //qDebug() << "refresh_serialport_null_flag index:" << refresh_serialport_null_flag;

    if(refresh_serialport_null_flag)
    {
        refresh_serialport_null_flag = false;
        on_searchButton_clicked();
        refresh_serialport_flag = false;
    }
}

void MainWindow::on_portNameBox_currentIndexChanged(int index)
{
    int Last_Com_ID = Com_ID;
    Com_ID = index;

    //TRACE_3(Last_Com_ID,Com_ID,SerialPortNum);

    if(SerialPortNum == 0 || Com_ID == -1 || Last_Com_ID == -1)
    {
        return;
    }

    if(Com_ID == SerialPortNum) //刷新串口
    {
        refresh_serialport_flag = true;
        on_searchButton_clicked();
        refresh_serialport_flag = false;
        return;
    }

    if(Last_Com_ID != Com_ID)
    {
        if(ui->btn_open_close_serial->text()==ClosePortStatus) //串口已经打开
        {
            //qDebug() << "串口打开时,动态切换串口";

            //关闭串口
            serial.close();

            Serial_Close_Status_Display();

            //状态栏显示打开关闭COM信息
            QString SerialComInfo = " ";
            SerialComInfo += ui->portNameBox->currentText() + " CLOSED";
            statusBarLabelSerial->setStyleSheet("color:red");
            statusBarLabelSerial->setText(SerialComInfo);

            on_btn_open_close_serial_clicked();
        }
    }
}

void MainWindow::on_baudrateBox_currentIndexChanged(int index)
{
    int Last_BaudRateID = BaudRateID;

    BaudRateID = index;

    if(Last_BaudRateID != BaudRateID)
    {
        if(ui->btn_open_close_serial->text()==ClosePortStatus) //串口已经打开
        {
            //qDebug() << "串口打开时,动态切换串口";

            //关闭串口
            serial.close();
            Serial_Close_Status_Display();

            //状态栏显示打开关闭COM信息
            QString SerialComInfo = " ";
            SerialComInfo += ui->portNameBox->currentText() + " CLOSED";
            statusBarLabelSerial->setStyleSheet("color:red");
            statusBarLabelSerial->setText(SerialComInfo);

            if(BaudRateID == 0) //custom
            {
                //qDebug() << "Custom";
                return;
            }

            on_btn_open_close_serial_clicked();
        }
        else
        {
            //qDebug() << "串口未打开时,不动态切换串口";
            ui->baudrateBox->setItemText(ui->baudrateBox->currentIndex(),ui->baudrateBox->currentText());
        }
    }
    else
    {
        ui->baudrateBox->setItemText(ui->baudrateBox->currentIndex(),ui->baudrateBox->currentText());
    }
}

void MainWindow::on_btn_open_close_serial_clicked()
{
    open_close_serial_port();
}

void MainWindow::Serial_Close_Status_Display()
{
    ui->checkBox_AutoSend->setChecked(0);
    fTimer->stop(); //定时器停止

    //下拉菜单控件使能
    ui->portNameBox->setEditable(true);
    ui->baudrateBox->setEditable(true);

    ui->dataBitsBox->setEnabled(true);
    ui->ParityBox->setEnabled(true);
    ui->stopBitsBox->setEnabled(true);
    ui->flowControlBox->setEnabled(true);

    ui->btn_open_close_serial->setText(OpenPortStatus);
}

void MainWindow::open_close_serial_port()
{
    //qDebug() << "baudrateBox" << ui->baudrateBox->currentText();

    if(ui->btn_open_close_serial->text()==OpenPortStatus)
    {
        //设置串口名
        serial.setPortName(ui->portNameBox->currentText());
        //设置波特率
        serial.setBaudRate(ui->baudrateBox->currentText().toInt());
        //设置数据位数
        //TRACE_1(ui->dataBitsBox->currentIndex());
        switch(ui->dataBitsBox->currentIndex())
        {
        case 0: serial.setDataBits(QSerialPort::Data5); break;
        case 1: serial.setDataBits(QSerialPort::Data6); break;
        case 2: serial.setDataBits(QSerialPort::Data7); break;
        case 3: serial.setDataBits(QSerialPort::Data8); break;
        default: break;
        }
        //设置奇偶校验
        //TRACE_1(ui->ParityBox->currentIndex());
        switch(ui->ParityBox->currentIndex())
        {
        case 0: serial.setParity(QSerialPort::NoParity); break;
        case 1: serial.setParity(QSerialPort::EvenParity); break;
        case 2: serial.setParity(QSerialPort::OddParity); break;
        case 3: serial.setParity(QSerialPort::SpaceParity); break;
        case 4: serial.setParity(QSerialPort::MarkParity); break;
        default: break;
        }
        //设置停止位
        //TRACE_1(ui->stopBitsBox->currentIndex());
        switch(ui->stopBitsBox->currentIndex())
        {
        case 0: serial.setStopBits(QSerialPort::OneStop); break;
        case 1: serial.setStopBits(QSerialPort::OneAndHalfStop); break;
        case 2: serial.setStopBits(QSerialPort::TwoStop); break;
        default: break;
        }
        //设置流控制
        //TRACE_1(ui->flowControlBox->currentIndex());
        switch(ui->flowControlBox->currentIndex())
        {
        case 0: serial.setFlowControl(QSerialPort::NoFlowControl); break;
        case 1: serial.setFlowControl(QSerialPort::HardwareControl); break;
        case 2: serial.setFlowControl(QSerialPort::SoftwareControl); break;
        default: break;
        }

        //打开串口
        if(!serial.open(QIODevice::ReadWrite))
        {
            Serial_Close_Status_Display();

            //状态栏显示打开关闭COM信息
            QString SerialComInfo = " ";

            SerialComInfo += ui->portNameBox->currentText() + " 串口打开失败! 错误: 拒绝访问(被占用).";
            statusBarLabelSerial->setStyleSheet("color:red");
            statusBarLabelSerial->setText(SerialComInfo);

            return;
        }

        //状态栏显示打开关闭COM信息
        QString SerialComInfo = " ";

        SerialComInfo += ui->portNameBox->currentText();
        SerialComInfo += " OPEND, ";
        SerialComInfo += ui->baudrateBox->currentText();
        SerialComInfo += ", ";
        SerialComInfo += ui->dataBitsBox->currentText();
        SerialComInfo += ", ";
        SerialComInfo += ui->ParityBox->currentText();
        SerialComInfo += ", ";
        SerialComInfo += ui->stopBitsBox->currentText();
        SerialComInfo += ", ";
        SerialComInfo += ui->flowControlBox->currentText();

        statusBarLabelSerial->setStyleSheet("color:green");
        statusBarLabelSerial->setText(SerialComInfo);

        //下拉菜单控件失能
        //设置不可编辑
        ui->baudrateBox->setItemText(ui->baudrateBox->currentIndex(),ui->baudrateBox->currentText());
        ui->portNameBox->setEditable(false);
        ui->baudrateBox->setEditable(false);
        ui->dataBitsBox->setEnabled(false);
        ui->ParityBox->setEnabled(false);
        ui->stopBitsBox->setEnabled(false);
        ui->flowControlBox->setEnabled(false);

        ui->btn_open_close_serial->setText(ClosePortStatus);

        WriteLogFileInit();
    }
    else
    {
        //关闭串口
        serial.close();
        Serial_Close_Status_Display();

        //状态栏显示打开关闭COM信息
        QString SerialComInfo = " ";
        SerialComInfo += ui->portNameBox->currentText() + " CLOSED";
        statusBarLabelSerial->setStyleSheet("color:red");
        statusBarLabelSerial->setText(SerialComInfo);
    }
}


bool MainWindow::SendDatePreJudgment()
{
    //TRACE_1(CommProType);

    if(ui->btn_open_close_serial->text()==QString(OpenPortStatus) && (CommProType == Serial_Comm))
    {
        QString SerialComInfo;

        //状态栏显示打开关闭COM信息
        SerialComInfo = " 请先打开串口";
        SerialComInfo += ui->portNameBox->currentText() + ",再发送数据!";
        statusBarLabelSerial->setStyleSheet("color:red");
        statusBarLabelSerial->setText(SerialComInfo);

        return false;
    }

    else if(ui->btn_open_close_bt->text()==QString(OpenBtStatus) && (CommProType == Bluetooth_Comm))
    {
        QString SerialComInfo;

        //状态栏显示打开关闭COM信息
        SerialComInfo = " 请打开蓝牙,再发送数据!";
        statusBarLabelBluetooth->setStyleSheet("color:red");
        statusBarLabelBluetooth->setText(SerialComInfo);

        return false;
    }

    return true;
}

void MainWindow::SetTxRxMsgcolor(QString Mode)
{
    //TRACE_2(Msgcolor_Configured,Msgcolor_Configured_temp);

    if(Mode=="TX" || Mode=="TX_BT")
    {
        if(Mode=="TX") Msgcolor_Configured = 1;
        else Msgcolor_Configured = 3;

        //字体&颜色
        if(Msgcolor_Configured != Msgcolor_Configured_temp)
        {
            Msgcolor_Configured_temp = Msgcolor_Configured;

            if(Mode=="TX")
            {
                SendMsgcolor.setRed(0x00);
                SendMsgcolor.setGreen(0x55);
                SendMsgcolor.setBlue(0xff);
            }
            else
            {
                SendMsgcolor.setRed(0xff);
                SendMsgcolor.setGreen(0x55);
                SendMsgcolor.setBlue(0xff);
            }
        }
    }
    else if(Mode=="RX")
    {
        Msgcolor_Configured = 2;

        //字体&颜色
        if(Msgcolor_Configured != Msgcolor_Configured_temp)
        {
            Msgcolor_Configured_temp = Msgcolor_Configured;
            SendMsgcolor.setRed(0x00);
            SendMsgcolor.setGreen(0xaa);
            SendMsgcolor.setBlue(0x00);
        }
    }

    TextCharFormat.setForeground(SendMsgcolor);
    ui->recvTextEdit->setCurrentCharFormat(TextCharFormat);
}

void MainWindow::on_sendButton_clicked()
{
    CommProType = Serial_Comm;

    SendAddItemFlag = true;

    if(!SendDatePreJudgment())
    {
        return;
    }

    if(ui->sendTextEdit->toPlainText().isEmpty()) //else if(ui->sendTextEdit->toPlainText()==QString(""))
    {
        ui->recvTextEdit->insertPlainText(StrEmpty);
        ui->recvTextEdit->append("");

        return;
    }

    SetTxRxMsgcolor("TX");

    QString dataStr = ui->sendTextEdit->toPlainText();
    //qDebug() << "dataStr:" << dataStr;

    if(ui->checkBox_hexSend->isChecked())
    {
        writeHex(dataStr);
    }
    else
    {
        writeAscii(dataStr);
    }

    if(SendAddItemFlag)
    {
        //发送数据增加到列表
        int count = ui->comboBox_sendHistory->count();

        if((count > 0) && (dataStr == ui->comboBox_sendHistory->itemText(count-1)))
        {
            //qDebug() << "last item same exit";
            return;
        }

        for(int i=0; i<count; i++)
        {
            QString StrItem = ui->comboBox_sendHistory->itemText(i);
            //qDebug() << StrItem;

            if(StrItem == dataStr)
            {
                //qDebug() << "have item same exit";
                SendAddItemFlag = false;
                break;
            }
        }

        if(SendAddItemFlag)
        {
            ui->comboBox_sendHistory->addItem(dataStr);
        }
    }
}

//--------------------------------------------发送数据------------------------------------------------------
//------------------------------------------------------
//30->0 46->F  3046-0F
void MainWindow::StringToHex(QString str, QByteArray &senddata) //字符串转换为十六进制数据0-F
{
    int hexdata,lowhexdata;
    int hexdatalen = 0;
    int len = str.length();
    senddata.resize(len / 2); //size()是分配容器的内存大小
    char lstr,hstr;

    for (int i = 0; i < len; ) //   str "012Abc0d"
    {
        hstr = str[i].toLatin1(); //'0'
        if (hstr == ' ')
        {
            ++i;
            continue; //空格略过,继续下一个循环
        }
        ++i;
        if (i  >= len)
        {
           break; //循环退出
        }
        lstr = str[i].toLatin1(); //'1'
        hexdata = ConvertHexChar(hstr);
        lowhexdata = ConvertHexChar(lstr);

        if ((hexdata == 16) || (lowhexdata == 16)) //正常(0-15),不会等于16
        {
            break;
        }
        else
        {
            hexdata = hexdata*16 + lowhexdata; //高低位组合
        }
        ++i;
        senddata[hexdatalen] = (unsigned char)hexdata; //写入buffer
        //qDebug("%02X ",(unsigned char)senddata[hexdatalen]);
        ++hexdatalen;
    }
    senddata.resize(hexdatalen);
}

//3046 -> 33 30 34 36
QString MainWindow::HexToAscii(QByteArray array)
{
    QString str = "";
    QString temp = array.toHex();

    for(int i = 0;i < temp.count();i++)
    {
        //在str的末尾插入一个元素
        str.push_back(temp.at(i)); //at()只读,访问速度最快

        if(i % 2 == 1 && i != 0)
        {
            str.push_back(' ');
        }
    }

    str = str.toUpper();

    return str;
}


char MainWindow::ConvertHexChar(char ch)
{
    if ((ch >= '0') && (ch <= '9'))
    {
        return ch - 0x30; //0-9
    }
    else if ((ch >= 'A') && (ch <= 'F'))
    {
        return ch - 'A' + 10; //10-15
    }
    else if ((ch >= 'a') && (ch <= 'f'))
    {
        return ch - 'a' + 10; //10-15
    }
    else
    {
        return ch - ch; //0 -> 其他非十六进制字符当作0处理
    }
}
//------------------------------------------------------

QByteArray MainWindow::DisplayTimestamp(QByteArray buffer)
{
    //显示时间戳:处理方法:
    //1.在输入的字符串前加时间戳,
    //2.再查找\n,替换为\n+时间戳,
    //3.根据"自动换行"按钮选择加入\r\n (无自动换行按钮默认加入\r\n)

    QByteArray data_backup = buffer;

    //获取当前日期时间,并转换为字符串
    QDateTime curDateTime = QDateTime::currentDateTime();
    QString CurRecvTime = curDateTime.toString(ReceiveTimeFormat);
    QByteArray ByteArrayCurSendTime = CurRecvTime.toLatin1();

    data_backup = ByteArrayCurSendTime + data_backup;
    QByteArray ReplaceCurRecvTime = "\n" + ByteArrayCurSendTime;
    data_backup.replace("\n",ReplaceCurRecvTime);

    if(ui->checkBox_AutoLineBreak->isChecked()) data_backup += "\r\n";

    return data_backup;
}


void MainWindow::WriteLogFileInit()
{
    if(!LogFileAlreadyOpen)
    {
        LogPathFileName = QCoreApplication::applicationDirPath() + "/" + "Serial_Bluetooth_Debug_Assistant_Log" + "/";
        LogPathFileName.replace("//","/"); //特殊处理盘符根目录下D://情况
        //LogPathFileName += ui->portNameBox->currentText() + "_";
        LogPathFileName += "Session_";
        QDateTime curDateTime=QDateTime::currentDateTime();

        LogPathFileName += curDateTime.toString("yyyy-MM-dd_hh") + ".txt"; //"[yyyy-MM-dd hh:mm:ss.zzz] "
        //qDebug() << LogPathFileName;

        //新建txt文件
        WriteLogFile = new QFile;
        WriteLogFile->setFileName(LogPathFileName);

        bool ok = WriteLogFile->open(QIODevice::WriteOnly|QIODevice::Append);

        if(ok)
        {
             QTextStream out(WriteLogFile);
             //qDebug() << "Log init";
             //out << ""; //转化成纯文本写入文件
             LogFileAlreadyOpen = true;

             //WriteLogFile->close();
             //delete(WriteLogFile);
        }
        else
        {
            ui->recvTextEdit->insertPlainText("保存日记失败!");
            ui->recvTextEdit->append("");
        }
    }
}

void MainWindow::WriteLogFileInfo(QString data)
{
    //写日记
    if(LogFileAlreadyOpen)
    {
        QString LogPathFileNameTemp = "Session_";
        QDateTime curDateTime=QDateTime::currentDateTime();

        LogPathFileNameTemp += curDateTime.toString("yyyy-MM-dd_hh") + ".txt"; //"[yyyy-MM-dd hh:mm:ss.zzz] "

        int num = LogPathFileName.lastIndexOf("/");
        QString PathSuffix = LogPathFileName.mid(num+1);

        if(LogPathFileNameTemp != PathSuffix)
        {
            LogPathFileName = LogPathFileName.replace(PathSuffix,LogPathFileNameTemp);
            //qDebug() << "LogPathFileName" << LogPathFileName;
            WriteLogFile = new QFile;
            WriteLogFile->setFileName(LogPathFileName);
            WriteLogFile->open(QIODevice::WriteOnly);
        }

        QTextStream out(WriteLogFile);
        out << data; //转化成纯文本写入文件
    }
}

void MainWindow::displayTxRxCount(const QString String, int Count)
{
    if(String == "TX")
    {
        SendTotailSize += Count;

        QString Size = "Tx: ";

        Size += QString::number(SendTotailSize);

        Size += " Bytes";

        statusBarLabelTx->setText(Size);
    }

    if(String == "RX")
    {
        ReceiveTotailSize += Count;

        QString Size = "Rx: ";

        Size += QString::number(ReceiveTotailSize);

        Size += " Bytes";

        statusBarLabelRx->setText(Size);
    }

}

void MainWindow::SendDataHandle(QByteArray data)
{
    //SetTxRxMsgcolor("TX");

    if(CommProType == Serial_Comm)
    {
        serial.write(data);
    }
    else if(CommProType == Bluetooth_Comm)
    {
        #ifdef __Bluetooth__
        //qDebug() << data;
        socket->write(data, data.size());
        #endif
    }
}

void MainWindow::writeAscii(QString dataStr)
{
    QByteArray data = dataStr.toUtf8();

     if(ui->checkBox_CR_LF->isChecked())
     {
         data.append('\r'); //0D
         data.append('\n'); //0A
     }

     //显示发送按钮 -- 只有显示发送才会有时间戳
     if(ui->checkBox_displaySend->isChecked())
     {
        if(CommProType == Serial_Comm || CommProType == Bluetooth_Comm)
        {
            QByteArray DisplayBuffer = data;

            //显示发送时间戳
            if(ui->checkBox_displayTime->isChecked() && !SendTimeFormat.isEmpty())
            {
                DisplayBuffer = DisplayTimestamp(DisplayBuffer);

                ui->recvTextEdit->insertPlainText(DisplayBuffer);
                WriteLogFileInfo(DisplayBuffer);
            }
            else
            {
                if(ui->checkBox_AutoLineBreak->isChecked()) DisplayBuffer += "\r\n";
                ui->recvTextEdit->insertPlainText(DisplayBuffer);
                WriteLogFileInfo(DisplayBuffer);
            }
        }
    }

    SendDataHandle(data);

    //状态栏显示发送数据个数
    displayTxRxCount("TX", data.size());
}

void MainWindow::writeHex(QString dataStr)
{
    //如果发送的数据个数为奇数的,则在前面最后落单的字符前添加一个字符0
    dataStr = dataStr.replace(" ","");

    if (dataStr.length() % 2) //dataStr.length()=7
    {
        dataStr.insert(dataStr.length()-1, '0'); //012Abcd -> 012Abc0d
    }

    QByteArray data;
    StringToHex(dataStr, data);

//    qDebug() << "dataStr" << dataStr;
//    qDebug() << "data" << data;
//
//    for(int i=0;i<data.size();i++)
//    {
//        qDebug("%02X ",(unsigned char)data[i]);
//    }

    if(ui->checkBox_CR_LF->isChecked())
    {
        data.append('\r');
        data.append('\n');
    }

    //显示发送按钮 -- 只有显示发送才会有时间戳
    if(ui->checkBox_displaySend->isChecked())
    {
        //显示用
        QString str = HexToAscii(data); //1234 ->12 34
        //qDebug() << "Hex str:" << str;

        if(CommProType == Serial_Comm || CommProType == Bluetooth_Comm)
        {
            QByteArray DisplayBuffer = str.toLatin1();;

            //显示发送时间戳
            if(ui->checkBox_displayTime->isChecked() && !SendTimeFormat.isEmpty())
            {
                DisplayBuffer = DisplayTimestamp(DisplayBuffer);

                ui->recvTextEdit->insertPlainText(DisplayBuffer);
                WriteLogFileInfo(DisplayBuffer);
            }
            else
            {
                if(ui->checkBox_AutoLineBreak->isChecked()) DisplayBuffer += "\r\n";
                ui->recvTextEdit->insertPlainText(DisplayBuffer);
                WriteLogFileInfo(DisplayBuffer);
            }
        }
    }

    SendDataHandle(data);

    //状态栏显示发送数据个数
    displayTxRxCount("TX", data.size());
}

void MainWindow::serialPort_readyRead()
{
    //从接收缓冲区中读取数据
    QByteArray buffer = serial.readAll();
    static int TotailBufferSize = 0;

    if(1)
    {
        //字体&颜色
        SetTxRxMsgcolor("RX");

        //状态栏显示接收数据个数
        displayTxRxCount("RX", buffer.size());

        TotailBufferSize += buffer.size();

        //显示接收时间戳
        if(ui->checkBox_displayTime->isChecked() && !ReceiveTimeFormat.isEmpty())
        {
            if(ui->checkBox_hexReceive->isChecked())
            {
                QString str = HexToAscii(buffer);
                QDateTime curDateTime=QDateTime::currentDateTime();
                QString CurRecvTime = curDateTime.toString(ReceiveTimeFormat);

                str = CurRecvTime + str;
                if(ui->checkBox_AutoLineBreak->isChecked()) str += "\r\n";

                ui->recvTextEdit->insertPlainText(str);
                WriteLogFileInfo(str);
            }
            else
            {
                QByteArray DisplayBuffer = DisplayTimestamp(buffer);

                //显示接收数据
                ui->recvTextEdit->insertPlainText(DisplayBuffer);
                WriteLogFileInfo(DisplayBuffer);
             }
        }

        if(TotailBufferSize >= 100*1024*1024) //100M
        {
            TotailBufferSize = 0;
            ui->recvTextEdit->clear();
        }
    }
}


void MainWindow::on_btn_clear_recevie_clicked()
{
    ui->recvTextEdit->clear();

    SendTotailSize = 0;
    ReceiveTotailSize = 0;
    statusBarLabelRx->setText("Rx: 0 Bytes"); //设置标签的名字
    statusBarLabelTx->setText("Tx: 0 Bytes"); //设置标签的名字
}

void MainWindow::on_btn_clear_send_clicked()
{
    ui->sendTextEdit->clear();
    ui->comboBox_sendHistory->clear();
}

//Qt中textEdit文本编辑区设置滚动条自动向下滑落
//https://blog.csdn.net/HHT0506/article/details/100567581
void MainWindow::on_recvTextEdit_textChanged()
{
    ui->recvTextEdit->moveCursor(QTextCursor::End);
}

void MainWindow::on_comboBox_sendHistory_activated(const QString &arg1)
{
    //qDebug() << arg1;
    SendAddItemFlag = false; //不增加到列表

    if(!SendDatePreJudgment())
    {
        return;
    }

    SetTxRxMsgcolor("TX");

    #ifdef __Bluetooth__
    if(CommProType == Bluetooth_Comm)
        SetTxRxMsgcolor("TX_BT");
    #endif

    if(ui->checkBox_hexSend->isChecked())
    {
        writeHex(arg1);
    }
    else
    {
        writeAscii(arg1);
    }
}

void MainWindow::on_checkBox_AutoSend_clicked()
{
    if(!SendDatePreJudgment())
    {
        ui->checkBox_AutoSend->setChecked(0);
        return;
    }

    if(ui->sendTextEdit->toPlainText().isEmpty()) //else if(ui->sendTextEdit->toPlainText()==QString(""))
    {
        ui->recvTextEdit->insertPlainText(StrEmpty);
        ui->recvTextEdit->append("");
        ui->checkBox_AutoSend->setChecked(0);
        return;
    }

    if(ui->checkBox_AutoSend->isChecked())
    {

        if(CommProType == Serial_Comm) on_sendButton_clicked();

        #ifdef __Bluetooth__
        else on_sendButton_bt_clicked();
        #endif

        AutoSendTimeMs = ui->spinBox_AutoSendTime->text().toInt(); //不能带单位,否则toInt变成了0
        //TRACE_1(AutoSendTimeMs);
        fTimer->setInterval (AutoSendTimeMs) ;//设置定时周期,单位:毫秒
        fTimer->start () ;//定时器开始工作 -- slot_timer_timeout
    }
    else
    {
        fTimer->stop() ; //定时器停止
    }
}

void MainWindow::closeEvent(QCloseEvent *event)
{
    Q_UNUSED(event);

    SaveSerialPortConfigParameters();
}

#endif

//---------------------------------蓝牙----------------------------------------

#ifdef __Bluetooth__

void MainWindow::BlueTooth_Reset()
{
    //初始化蓝牙搜索类
    discoveryAgent = new QBluetoothDeviceDiscoveryAgent();
    //为本地蓝牙创建描述类
    localDevice = new QBluetoothLocalDevice();
    // 给socket分配内存,限定套接字协议
    socket = new QBluetoothSocket(QBluetoothServiceInfo::RfcommProtocol);
    //判断蓝牙是否开启,若开启则不可被选中并扫描周围蓝牙设备

    // 发现设备时会触发deviceDiscovered信号,转到槽显示蓝牙设备
    connect(discoveryAgent, SIGNAL(deviceDiscovered(QBluetoothDeviceInfo)), this, SLOT(addBlueToothDevicesToList(QBluetoothDeviceInfo)));
    connect(discoveryAgent, SIGNAL(finished()), this, SLOT(findFinish()));
    //双击listwidget的项目,触发连接蓝牙的槽
    connect(ui->listWidget, SIGNAL(itemActivated(QListWidgetItem *)), this, SLOT(connectBLE(QListWidgetItem *)));
    connect(socket, SIGNAL(connected()), this, SLOT(connectOK()));
    connect(socket, SIGNAL(disconnected()), this, SLOT(connectNot()));
    connect(socket, SIGNAL(readyRead()), this, SLOT(readBluetoothDataEvent()));
}

bool MainWindow::BlueTooth_Init()
{
    BlueTooth_Reset();

    //qDebug() << "localDevice->hostMode()" << localDevice->hostMode();
    //localDevice->hostMode() QBluetoothLocalDevice::HostConnectable
    ui->btn_update->setEnabled(false);

    if (localDevice->hostMode() == QBluetoothLocalDevice::HostPoweredOff)
    {
        // 开始扫描蓝牙设备
        //discoveryAgent->start();

        return false;
    }
    else
    {
        localDevice->powerOn();

        ui->listWidget->clear();
        // 开始扫描蓝牙设备
        discoveryAgent->start();

        return true;
    }
}


void MainWindow::open_close_bluetooth()
{
    if(ui->btn_open_close_bt->text()==OpenBtStatus)
    {
        if(BlueTooth_Init())
        {
            WriteLogFileInit();
            //状态栏显示打开关闭COM信息
            QString StatusInfo = " ";
            StatusInfo += "Bluetooth Scanning...";
            statusBarLabelBluetooth->setStyleSheet("color:green");
            statusBarLabelBluetooth->setText(StatusInfo);

            ui->btn_open_close_bt->setText(CloseBtStatus);
        }
        else
        {
            ui->btn_open_close_bt->setText(OpenBtStatus);
            //状态栏显示打开关闭COM信息
            QString StatusInfo = " ";
            StatusInfo += "Bluetooth Init Fail!";
            statusBarLabelBluetooth->setStyleSheet("color:red");
            statusBarLabelBluetooth->setText(StatusInfo);
        }
    }
    else
    {
        discoveryAgent->stop(); //停止搜索设备

        CloseBluetooth_Status_Display();
    }
}

void MainWindow::CloseBluetooth_Status_Display()
{
    #ifdef __Serial__
    ui->checkBox_AutoSend->setChecked(0);
    fTimer->stop(); //定时器停止
    #endif
    
    ui->btn_open_close_bt->setText(OpenBtStatus);

    bool EnabledFlag = false;
    ui->btn_update->setEnabled(EnabledFlag);

    //状态栏显示打开关闭COM信息
    QString StatusInfo = " ";
    StatusInfo += "Bluetooth Close!";
    statusBarLabelBluetooth->setStyleSheet("color:red");
    statusBarLabelBluetooth->setText(StatusInfo);
}

void MainWindow::findFinish()
{
    ui->btn_update->setEnabled(true);
    //TRACE_0_STR("");

    //状态栏显示打开关闭COM信息
    QString StatusInfo = " ";
    StatusInfo += "Scan Finish";
    statusBarLabelBluetooth->setStyleSheet("color:green");
    statusBarLabelBluetooth->setText(StatusInfo);
}

void MainWindow::connectOK()
{
    discoveryAgent->stop(); //停止搜索设备
    //QMessageBox::information(this, tr("成功"), tr("连接成功!"));

    //状态栏显示打开关闭COM信息
    QString StatusInfo = " ";
    StatusInfo += "Connected.";
    statusBarLabelBluetooth->setStyleSheet("color:green");
    statusBarLabelBluetooth->setText(StatusInfo);
}

void MainWindow::connectNot()
{
    //QMessageBox::information(this, tr("错误"), tr("连接失败!"));

    //状态栏显示打开关闭COM信息
    QString StatusInfo = " ";
    StatusInfo += "Disconnected!";
    statusBarLabelBluetooth->setStyleSheet("color:red");
    statusBarLabelBluetooth->setText(StatusInfo);
    BlueTooth_Reset();
}

void MainWindow::readBluetoothDataEvent()
{
    //从接收缓冲区中读取数据
    QByteArray buffer = socket->readAll();
    static int TotailBufferSize = 0;

    if(1)
    {
        //字体&颜色
        SetTxRxMsgcolor("RX");

        //状态栏显示接收数据个数
        displayTxRxCount("RX", buffer.size());

        TotailBufferSize += buffer.size();

        //显示接收时间戳
        if(ui->checkBox_displayTime->isChecked() && !ReceiveTimeFormat.isEmpty())
        {
            if(ui->checkBox_hexReceive->isChecked())
            {
                QString str = HexToAscii(buffer);
                QDateTime curDateTime=QDateTime::currentDateTime();
                QString CurRecvTime = curDateTime.toString(ReceiveTimeFormat);

                str = CurRecvTime + str;
                if(ui->checkBox_AutoLineBreak->isChecked()) str += "\r\n";

                ui->recvTextEdit->insertPlainText(str);
                WriteLogFileInfo(str);
            }
            else
            {
                QByteArray DisplayBuffer = DisplayTimestamp(buffer);

                //显示接收数据
                ui->recvTextEdit->insertPlainText(DisplayBuffer);
                WriteLogFileInfo(DisplayBuffer);
             }
        }

        if(TotailBufferSize >= 100*1024*1024) //100M
        {
            TotailBufferSize = 0;
            ui->recvTextEdit->clear();
        }
    }
}

#define BlueToothDevicesDefaultDisplay
void MainWindow::addBlueToothDevicesToList(QBluetoothDeviceInfo info)
{
    #if defined (BlueToothDevicesDefaultDisplay)
    QString label= QString("%1 %2").arg(info.address().toString()).arg(info.name());
    #else
    QString label = QString("%1\n%2").arg(info.name()).arg(info.address().toString());
    #endif

    QList<QListWidgetItem *> items = ui->listWidget->findItems(label, Qt::MatchExactly);

    if (items.empty())
    {
        QListWidgetItem *item = new QListWidgetItem(label);
        QBluetoothLocalDevice::Pairing pairingStatus = localDevice->pairingStatus(info.address());
        //qDebug() << info.name() << info.address() << "pairingStatus:" << pairingStatus;

        /* 蓝牙状态pairingStatus,
           Pairing枚举类型
           0:Unpaired没配对
           1:Paired配对但没授权
           2:AuthorizedPaired配对且授权
        */

        if (pairingStatus == QBluetoothLocalDevice::Paired || pairingStatus == QBluetoothLocalDevice::AuthorizedPaired)
        {
            item->setForeground(QColor(Qt::green));
        }
        else
        {
            item->setForeground(QColor(Qt::black));
        }
        ui->listWidget->addItem(item);
    }
}

void MainWindow::connectBLE(QListWidgetItem *item)
{
    static const QLatin1String serviceUuid("00001101-0000-1000-8000-00805F9B34FB");//百度来的手机连接单片机用的uuid
    QString text = item->text(); //蓝牙和地址

    #if defined (BlueToothDevicesDefaultDisplay)
    int index = text.indexOf(' ');

    if(index == -1) return;

    QBluetoothAddress address(text.left(index));

    QString name(text.mid(index + 1));

    #else

    int index = text.indexOf('\n');

    if(index == -1) return;

    QBluetoothAddress address(text.mid(index + 1));

    QString name(text.mid(0,index));

    #endif

    //状态栏显示打开关闭COM信息
    QString StatusInfo = " ";

    if(socket->state()==0) //UnconnectedState
    {
        StatusInfo += "Bluetooth is connecting. Please wait...";
        statusBarLabelBluetooth->setStyleSheet("color:green");
        statusBarLabelBluetooth->setText(StatusInfo);
        socket->connectToService(address, QBluetoothUuid(serviceUuid),QIODevice::ReadWrite);
    }
    else if(socket->state()==1) // ServiceLookupState
    {
        StatusInfo += "Bluetooth is ServiceLookupState.";
        statusBarLabelBluetooth->setStyleSheet("color:green");
        statusBarLabelBluetooth->setText(StatusInfo);
        socket->connectToService(address, QBluetoothUuid(serviceUuid),QIODevice::ReadWrite);
    }
    else if(socket->state()==3) // ConnectedState
    {
        StatusInfo += "Bluetooth is ConnectedState, Exit.";
        statusBarLabelBluetooth->setStyleSheet("color:blue");
        statusBarLabelBluetooth->setText(StatusInfo);
    }
    else
    {
        StatusInfo += "Bluetooth Connect Erorr.";
        statusBarLabelBluetooth->setStyleSheet("color:red");
        statusBarLabelBluetooth->setText(StatusInfo);
    }
}

void MainWindow::on_btn_update_clicked()
{
    //状态栏显示打开关闭COM信息
    QString StatusInfo = " ";
    StatusInfo += "Update Bluetooth List";
    statusBarLabelBluetooth->setStyleSheet("color:green");
    statusBarLabelBluetooth->setText(StatusInfo);

    BlueTooth_Reset();

    //socket->disconnectFromService();
    ui->listWidget->clear();
    discoveryAgent->start();
    ui->btn_update->setEnabled(false);
}

void MainWindow::on_btn_open_close_bt_clicked()
{
    open_close_bluetooth();
}

void MainWindow::on_sendButton_bt_clicked()
{
    CommProType = Bluetooth_Comm;

    SendAddItemFlag = true;

    if(!SendDatePreJudgment())
    {
        return;
    }

    if(ui->sendTextEdit->toPlainText().isEmpty()) //else if(ui->sendTextEdit->toPlainText()==QString(""))
    {
        ui->recvTextEdit->insertPlainText(StrEmpty);
        ui->recvTextEdit->append("");

        return;
    }

    SetTxRxMsgcolor("TX_BT");

    QString dataStr = ui->sendTextEdit->toPlainText();
    //qDebug() << "dataStr:" << dataStr;

    if(ui->checkBox_hexSend->isChecked())
    {
        writeHex(dataStr);
    }
    else
    {
        writeAscii(dataStr);
    }

    if(SendAddItemFlag)
    {
        //发送数据增加到列表
        int count = ui->comboBox_sendHistory->count();

        if((count > 0) && (dataStr == ui->comboBox_sendHistory->itemText(count-1)))
        {
            //qDebug() << "last item same exit";
            return;
        }

        for(int i=0; i<count; i++)
        {
            QString StrItem = ui->comboBox_sendHistory->itemText(i);
            //qDebug() << StrItem;

            if(StrItem == dataStr)
            {
                //qDebug() << "have item same exit";
                SendAddItemFlag = false;
                break;
            }
        }

        if(SendAddItemFlag)
        {
            ui->comboBox_sendHistory->addItem(dataStr);
        }
    }
}


#endif

四、获取 >> 源码以及Git记录:

Qt5串口蓝牙调试助手_V1.0(初级篇)_源码以及Git记录


总结

欢迎下载&更新使用。

  • 10
    点赞
  • 46
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Bingo缤果

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值