新增串口调试助手
parent
82155f24fc
commit
46ec08b3fd
|
@ -0,0 +1,7 @@
|
|||
HEADERS += \
|
||||
$$PWD/app.h \
|
||||
$$PWD/quiwidget.h
|
||||
|
||||
SOURCES += \
|
||||
$$PWD/app.cpp \
|
||||
$$PWD/quiwidget.cpp
|
|
@ -0,0 +1,201 @@
|
|||
#include "app.h"
|
||||
#include "quiwidget.h"
|
||||
|
||||
QString App::ConfigFile = "config.ini";
|
||||
QString App::SendFileName = "send.txt";
|
||||
QString App::DeviceFileName = "device.txt";
|
||||
|
||||
QString App::PortName = "COM1";
|
||||
int App::BaudRate = 9600;
|
||||
int App::DataBit = 8;
|
||||
QString App::Parity = "无";
|
||||
double App::StopBit = 1;
|
||||
|
||||
bool App::HexSend = false;
|
||||
bool App::HexReceive = false;
|
||||
bool App::Debug = false;
|
||||
bool App::AutoClear = false;
|
||||
|
||||
bool App::AutoSend = false;
|
||||
int App::SendInterval = 1000;
|
||||
bool App::AutoSave = false;
|
||||
int App::SaveInterval = 5000;
|
||||
|
||||
QString App::Mode = "Tcp_Client";
|
||||
QString App::ServerIP = "127.0.0.1";
|
||||
int App::ServerPort = 6000;
|
||||
int App::ListenPort = 6000;
|
||||
int App::SleepTime = 100;
|
||||
bool App::AutoConnect = false;
|
||||
|
||||
void App::readConfig()
|
||||
{
|
||||
if (!checkConfig()) {
|
||||
return;
|
||||
}
|
||||
|
||||
QSettings set(App::ConfigFile, QSettings::IniFormat);
|
||||
|
||||
set.beginGroup("ComConfig");
|
||||
App::PortName = set.value("PortName").toString();
|
||||
App::BaudRate = set.value("BaudRate").toInt();
|
||||
App::DataBit = set.value("DataBit").toInt();
|
||||
App::Parity = set.value("Parity").toString();
|
||||
App::StopBit = set.value("StopBit").toInt();
|
||||
|
||||
App::HexSend = set.value("HexSend").toBool();
|
||||
App::HexReceive = set.value("HexReceive").toBool();
|
||||
App::Debug = set.value("Debug").toBool();
|
||||
App::AutoClear = set.value("AutoClear").toBool();
|
||||
|
||||
App::AutoSend = set.value("AutoSend").toBool();
|
||||
App::SendInterval = set.value("SendInterval").toInt();
|
||||
App::AutoSave = set.value("AutoSave").toBool();
|
||||
App::SaveInterval = set.value("SaveInterval").toInt();
|
||||
set.endGroup();
|
||||
|
||||
set.beginGroup("NetConfig");
|
||||
App::Mode = set.value("Mode").toString();
|
||||
App::ServerIP = set.value("ServerIP").toString();
|
||||
App::ServerPort = set.value("ServerPort").toInt();
|
||||
App::ListenPort = set.value("ListenPort").toInt();
|
||||
App::SleepTime = set.value("SleepTime").toInt();
|
||||
App::AutoConnect = set.value("AutoConnect").toBool();
|
||||
set.endGroup();
|
||||
}
|
||||
|
||||
void App::writeConfig()
|
||||
{
|
||||
QSettings set(App::ConfigFile, QSettings::IniFormat);
|
||||
|
||||
set.beginGroup("ComConfig");
|
||||
set.setValue("PortName", App::PortName);
|
||||
set.setValue("BaudRate", App::BaudRate);
|
||||
set.setValue("DataBit", App::DataBit);
|
||||
set.setValue("Parity", App::Parity);
|
||||
set.setValue("StopBit", App::StopBit);
|
||||
|
||||
set.setValue("HexSend", App::HexSend);
|
||||
set.setValue("HexReceive", App::HexReceive);
|
||||
set.setValue("Debug", App::Debug);
|
||||
set.setValue("AutoClear", App::AutoClear);
|
||||
|
||||
set.setValue("AutoSend", App::AutoSend);
|
||||
set.setValue("SendInterval", App::SendInterval);
|
||||
set.setValue("AutoSave", App::AutoSave);
|
||||
set.setValue("SaveInterval", App::SaveInterval);
|
||||
set.endGroup();
|
||||
|
||||
set.beginGroup("NetConfig");
|
||||
set.setValue("Mode", App::Mode);
|
||||
set.setValue("ServerIP", App::ServerIP);
|
||||
set.setValue("ServerPort", App::ServerPort);
|
||||
set.setValue("ListenPort", App::ListenPort);
|
||||
set.setValue("SleepTime", App::SleepTime);
|
||||
set.setValue("AutoConnect", App::AutoConnect);
|
||||
set.endGroup();
|
||||
}
|
||||
|
||||
void App::newConfig()
|
||||
{
|
||||
#if (QT_VERSION <= QT_VERSION_CHECK(5,0,0))
|
||||
App::Parity = App::Parity.toLatin1();
|
||||
#endif
|
||||
writeConfig();
|
||||
}
|
||||
|
||||
bool App::checkConfig()
|
||||
{
|
||||
//如果配置文件大小为0,则以初始值继续运行,并生成配置文件
|
||||
QFile file(App::ConfigFile);
|
||||
if (file.size() == 0) {
|
||||
newConfig();
|
||||
return false;
|
||||
}
|
||||
|
||||
//如果配置文件不完整,则以初始值继续运行,并生成配置文件
|
||||
if (file.open(QFile::ReadOnly)) {
|
||||
bool ok = true;
|
||||
while (!file.atEnd()) {
|
||||
QString line = file.readLine();
|
||||
line = line.replace("\r", "");
|
||||
line = line.replace("\n", "");
|
||||
QStringList list = line.split("=");
|
||||
|
||||
if (list.count() == 2) {
|
||||
if (list.at(1) == "") {
|
||||
ok = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!ok) {
|
||||
newConfig();
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
newConfig();
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
QStringList App::Intervals = QStringList();
|
||||
QStringList App::Datas = QStringList();
|
||||
QStringList App::Keys = QStringList();
|
||||
QStringList App::Values = QStringList();
|
||||
|
||||
void App::readSendData()
|
||||
{
|
||||
//读取发送数据列表
|
||||
App::Datas.clear();
|
||||
QString fileName = QString("%1/%2").arg(QUIHelper::appPath()).arg(App::SendFileName);
|
||||
QFile file(fileName);
|
||||
if (file.size() > 0 && file.open(QFile::ReadOnly | QIODevice::Text)) {
|
||||
while (!file.atEnd()) {
|
||||
QString line = file.readLine();
|
||||
line = line.trimmed();
|
||||
line = line.replace("\r", "");
|
||||
line = line.replace("\n", "");
|
||||
if (!line.isEmpty()) {
|
||||
App::Datas.append(line);
|
||||
}
|
||||
}
|
||||
|
||||
file.close();
|
||||
}
|
||||
}
|
||||
|
||||
void App::readDeviceData()
|
||||
{
|
||||
//读取转发数据列表
|
||||
App::Keys.clear();
|
||||
App::Values.clear();
|
||||
QString fileName = QString("%1/%2").arg(QUIHelper::appPath()).arg(App::DeviceFileName);
|
||||
QFile file(fileName);
|
||||
if (file.size() > 0 && file.open(QFile::ReadOnly | QIODevice::Text)) {
|
||||
while (!file.atEnd()) {
|
||||
QString line = file.readLine();
|
||||
line = line.trimmed();
|
||||
line = line.replace("\r", "");
|
||||
line = line.replace("\n", "");
|
||||
if (!line.isEmpty()) {
|
||||
QStringList list = line.split(";");
|
||||
QString key = list.at(0);
|
||||
QString value;
|
||||
for (int i = 1; i < list.count(); i++) {
|
||||
value += QString("%1;").arg(list.at(i));
|
||||
}
|
||||
|
||||
//去掉末尾分号
|
||||
value = value.mid(0, value.length() - 1);
|
||||
App::Keys.append(key);
|
||||
App::Values.append(value);
|
||||
}
|
||||
}
|
||||
|
||||
file.close();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,51 @@
|
|||
#ifndef APP_H
|
||||
#define APP_H
|
||||
|
||||
#include "head.h"
|
||||
|
||||
class App
|
||||
{
|
||||
public:
|
||||
static QString ConfigFile; //配置文件路径
|
||||
static QString SendFileName; //发送配置文件名
|
||||
static QString DeviceFileName; //模拟设备数据文件名
|
||||
|
||||
static QString PortName; //串口号
|
||||
static int BaudRate; //波特率
|
||||
static int DataBit; //数据位
|
||||
static QString Parity; //校验位
|
||||
static double StopBit; //停止位
|
||||
|
||||
static bool HexSend; //16进制发送
|
||||
static bool HexReceive; //16进制接收
|
||||
static bool Debug; //模拟设备
|
||||
static bool AutoClear; //自动清空
|
||||
|
||||
static bool AutoSend; //自动发送
|
||||
static int SendInterval; //自动发送间隔
|
||||
static bool AutoSave; //自动保存
|
||||
static int SaveInterval; //自动保存间隔
|
||||
|
||||
static QString Mode; //转换模式
|
||||
static QString ServerIP; //服务器IP
|
||||
static int ServerPort; //服务器端口
|
||||
static int ListenPort; //监听端口
|
||||
static int SleepTime; //延时时间
|
||||
static bool AutoConnect; //自动重连
|
||||
|
||||
//读写配置参数及其他操作
|
||||
static void readConfig(); //读取配置参数
|
||||
static void writeConfig(); //写入配置参数
|
||||
static void newConfig(); //以初始值新建配置文件
|
||||
static bool checkConfig(); //校验配置文件
|
||||
|
||||
static QStringList Intervals;
|
||||
static QStringList Datas;
|
||||
static QStringList Keys;
|
||||
static QStringList Values;
|
||||
static void readSendData();
|
||||
static void readDeviceData();
|
||||
|
||||
};
|
||||
|
||||
#endif // APP_H
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,871 @@
|
|||
#ifndef QUIWIDGET_H
|
||||
#define QUIWIDGET_H
|
||||
|
||||
#define TIMEMS qPrintable(QTime::currentTime().toString("HH:mm:ss zzz"))
|
||||
#define TIME qPrintable(QTime::currentTime().toString("HH:mm:ss"))
|
||||
#define QDATE qPrintable(QDate::currentDate().toString("yyyy-MM-dd"))
|
||||
#define QTIME qPrintable(QTime::currentTime().toString("HH-mm-ss"))
|
||||
#define DATETIME qPrintable(QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss"))
|
||||
#define STRDATETIME qPrintable(QDateTime::currentDateTime().toString("yyyy-MM-dd-HH-mm-ss"))
|
||||
#define STRDATETIMEMS qPrintable(QDateTime::currentDateTime().toString("yyyy-MM-dd-HH-mm-ss-zzz"))
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
#define NEWLINE "\r\n"
|
||||
#else
|
||||
#define NEWLINE "\n"
|
||||
#endif
|
||||
|
||||
#ifdef __arm__
|
||||
#define TitleMinSize 40
|
||||
#else
|
||||
#define TitleMinSize 30
|
||||
#endif
|
||||
|
||||
/**
|
||||
* QUI无边框窗体控件 作者:feiyangqingyun(QQ:517216493)
|
||||
* 1:内置 N >= 17 套精美样式,可直接切换,也可自定义样式路径
|
||||
* 2:可设置部件(左上角图标/最小化按钮/最大化按钮/关闭按钮)的图标或者图片及是否可见
|
||||
* 3:可集成设计师插件,直接拖曳使用,所见即所得
|
||||
* 4:如果需要窗体可拖动大小,设置 setSizeGripEnabled(true);
|
||||
* 5:可设置全局样式 setStyle
|
||||
* 6:可弹出消息框,可选阻塞模式和不阻塞,默认不阻塞 showMessageBoxInfo
|
||||
* 7:可弹出错误框,可选阻塞模式和不阻塞,默认不阻塞 showMessageBoxError
|
||||
* 8:可弹出询问框 showMessageBoxError
|
||||
* 9:可弹出右下角信息框 showTipBox
|
||||
* 10:可弹出输入框 showInputBox
|
||||
* 11:可弹出时间范围选择框 showDateSelect
|
||||
* 12:消息框支持设置倒计时关闭
|
||||
* 13:集成图形字体设置方法及根据指定文字获取图片
|
||||
* 14:集成设置窗体居中显示/设置翻译文件/设置编码/设置延时/设置系统时间等静态方法
|
||||
* 15:集成获取应用程序文件名/文件路径 等方法
|
||||
*/
|
||||
|
||||
#include "head.h"
|
||||
|
||||
#ifdef quc
|
||||
#if (QT_VERSION < QT_VERSION_CHECK(5,7,0))
|
||||
#include <QtDesigner/QDesignerExportWidget>
|
||||
#else
|
||||
#include <QtUiPlugin/QDesignerExportWidget>
|
||||
#endif
|
||||
|
||||
class QDESIGNER_WIDGET_EXPORT QUIWidget : public QDialog
|
||||
#else
|
||||
class QUIWidget : public QDialog
|
||||
#endif
|
||||
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_ENUMS(Style)
|
||||
Q_PROPERTY(QString title READ getTitle WRITE setTitle)
|
||||
Q_PROPERTY(Qt::Alignment alignment READ getAlignment WRITE setAlignment)
|
||||
Q_PROPERTY(bool minHide READ getMinHide WRITE setMinHide)
|
||||
Q_PROPERTY(bool exitAll READ getExitAll WRITE setExitAll)
|
||||
|
||||
public:
|
||||
//将部分对象作为枚举值暴露给外部
|
||||
enum Widget {
|
||||
Lab_Ico = 0, //左上角图标
|
||||
BtnMenu = 1, //下拉菜单按钮
|
||||
BtnMenu_Min = 2, //最小化按钮
|
||||
BtnMenu_Max = 3, //最大化按钮
|
||||
BtnMenu_Normal = 4, //还原按钮
|
||||
BtnMenu_Close = 5 //关闭按钮
|
||||
};
|
||||
|
||||
//样式枚举
|
||||
enum Style {
|
||||
Style_Silvery = 0, //银色样式
|
||||
Style_Blue = 1, //蓝色样式
|
||||
Style_LightBlue = 2, //淡蓝色样式
|
||||
Style_DarkBlue = 3, //深蓝色样式
|
||||
Style_Gray = 4, //灰色样式
|
||||
Style_LightGray = 5, //浅灰色样式
|
||||
Style_DarkGray = 6, //深灰色样式
|
||||
Style_Black = 7, //黑色样式
|
||||
Style_LightBlack = 8, //浅黑色样式
|
||||
Style_DarkBlack = 9, //深黑色样式
|
||||
Style_PSBlack = 10, //PS黑色样式
|
||||
Style_FlatBlack = 11, //黑色扁平样式
|
||||
Style_FlatWhite = 12, //白色扁平样式
|
||||
Style_FlatBlue = 13, //蓝色扁平样式
|
||||
Style_Purple = 14, //紫色样式
|
||||
Style_BlackBlue = 15, //黑蓝色样式
|
||||
Style_BlackVideo = 16 //视频监控黑色样式
|
||||
};
|
||||
|
||||
public:
|
||||
explicit QUIWidget(QWidget *parent = 0);
|
||||
~QUIWidget();
|
||||
|
||||
protected:
|
||||
bool eventFilter(QObject *watched, QEvent *event);
|
||||
|
||||
private:
|
||||
QVBoxLayout *verticalLayout1;
|
||||
QWidget *widgetMain;
|
||||
QVBoxLayout *verticalLayout2;
|
||||
QWidget *widgetTitle;
|
||||
QHBoxLayout *horizontalLayout4;
|
||||
QLabel *labIco;
|
||||
QLabel *labTitle;
|
||||
QWidget *widgetMenu;
|
||||
QHBoxLayout *horizontalLayout;
|
||||
QToolButton *btnMenu;
|
||||
QPushButton *btnMenu_Min;
|
||||
QPushButton *btnMenu_Max;
|
||||
QPushButton *btnMenu_Close;
|
||||
QWidget *widget;
|
||||
QVBoxLayout *verticalLayout3;
|
||||
|
||||
private:
|
||||
QString title; //标题
|
||||
Qt::Alignment alignment; //标题文本对齐
|
||||
bool minHide; //最小化隐藏
|
||||
bool exitAll; //退出整个程序
|
||||
QWidget *mainWidget; //主窗体对象
|
||||
|
||||
public:
|
||||
QLabel *getLabIco() const;
|
||||
QLabel *getLabTitle() const;
|
||||
QToolButton *getBtnMenu() const;
|
||||
QPushButton *getBtnMenuMin() const;
|
||||
QPushButton *getBtnMenuMax() const;
|
||||
QPushButton *getBtnMenuMClose() const;
|
||||
|
||||
QString getTitle() const;
|
||||
Qt::Alignment getAlignment() const;
|
||||
bool getMinHide() const;
|
||||
bool getExitAll() const;
|
||||
|
||||
QSize sizeHint() const;
|
||||
QSize minimumSizeHint() const;
|
||||
|
||||
private slots:
|
||||
void initControl(); //初始化控件
|
||||
void initForm(); //初始化窗体
|
||||
void changeStyle(); //更换样式
|
||||
|
||||
private slots:
|
||||
void on_btnMenu_Min_clicked();
|
||||
void on_btnMenu_Max_clicked();
|
||||
void on_btnMenu_Close_clicked();
|
||||
|
||||
public Q_SLOTS:
|
||||
//设置部件图标
|
||||
void setIcon(QUIWidget::Widget widget, const QChar &str, quint32 size = 12);
|
||||
void setIconMain(const QChar &str, quint32 size = 12);
|
||||
//设置部件图片
|
||||
void setPixmap(QUIWidget::Widget widget, const QString &file, const QSize &size = QSize(16, 16));
|
||||
//设置部件是否可见
|
||||
void setVisible(QUIWidget::Widget widget, bool visible = true);
|
||||
//设置只有关闭按钮
|
||||
void setOnlyCloseBtn();
|
||||
|
||||
//设置标题栏高度
|
||||
void setTitleHeight(int height);
|
||||
//设置按钮统一宽度
|
||||
void setBtnWidth(int width);
|
||||
|
||||
//设置标题及文本样式
|
||||
void setTitle(const QString &title);
|
||||
void setAlignment(Qt::Alignment alignment);
|
||||
|
||||
//设置最小化隐藏
|
||||
void setMinHide(bool minHide);
|
||||
|
||||
//设置退出时候直接退出整个应用程序
|
||||
void setExitAll(bool exitAll);
|
||||
|
||||
//设置主窗体
|
||||
void setMainWidget(QWidget *mainWidget);
|
||||
|
||||
Q_SIGNALS:
|
||||
void changeStyle(const QString &qssFile);
|
||||
void closing();
|
||||
};
|
||||
|
||||
//弹出信息框类
|
||||
class QUIMessageBox : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
static QUIMessageBox *Instance();
|
||||
explicit QUIMessageBox(QWidget *parent = 0);
|
||||
~QUIMessageBox();
|
||||
|
||||
protected:
|
||||
void closeEvent(QCloseEvent *);
|
||||
bool eventFilter(QObject *watched, QEvent *event);
|
||||
|
||||
private:
|
||||
static QScopedPointer<QUIMessageBox> self;
|
||||
|
||||
QVBoxLayout *verticalLayout1;
|
||||
QWidget *widgetTitle;
|
||||
QHBoxLayout *horizontalLayout3;
|
||||
QLabel *labIco;
|
||||
QLabel *labTitle;
|
||||
QLabel *labTime;
|
||||
QWidget *widgetMenu;
|
||||
QHBoxLayout *horizontalLayout4;
|
||||
QPushButton *btnMenu_Close;
|
||||
QWidget *widgetMain;
|
||||
QVBoxLayout *verticalLayout2;
|
||||
QFrame *frame;
|
||||
QVBoxLayout *verticalLayout4;
|
||||
QHBoxLayout *horizontalLayout1;
|
||||
QLabel *labIcoMain;
|
||||
QSpacerItem *horizontalSpacer1;
|
||||
QLabel *labInfo;
|
||||
QHBoxLayout *horizontalLayout2;
|
||||
QSpacerItem *horizontalSpacer2;
|
||||
QPushButton *btnOk;
|
||||
QPushButton *btnCancel;
|
||||
|
||||
private:
|
||||
int closeSec; //总显示时间
|
||||
int currentSec; //当前已显示时间
|
||||
|
||||
private slots:
|
||||
void initControl(); //初始化控件
|
||||
void initForm(); //初始化窗体
|
||||
void checkSec(); //校验倒计时
|
||||
|
||||
private slots:
|
||||
void on_btnOk_clicked();
|
||||
void on_btnMenu_Close_clicked();
|
||||
|
||||
public Q_SLOTS:
|
||||
void setIconMain(const QChar &str, quint32 size = 12);
|
||||
void setMessage(const QString &msg, int type, int closeSec = 0);
|
||||
};
|
||||
|
||||
//右下角弹出框类
|
||||
class QUITipBox : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
static QUITipBox *Instance();
|
||||
explicit QUITipBox(QWidget *parent = 0);
|
||||
~QUITipBox();
|
||||
|
||||
protected:
|
||||
void closeEvent(QCloseEvent *);
|
||||
bool eventFilter(QObject *watched, QEvent *event);
|
||||
|
||||
private:
|
||||
static QScopedPointer<QUITipBox> self;
|
||||
|
||||
QVBoxLayout *verticalLayout;
|
||||
QWidget *widgetTitle;
|
||||
QHBoxLayout *horizontalLayout2;
|
||||
QLabel *labIco;
|
||||
QLabel *labTitle;
|
||||
QLabel *labTime;
|
||||
QWidget *widgetMenu;
|
||||
QHBoxLayout *horizontalLayout;
|
||||
QPushButton *btnMenu_Close;
|
||||
QWidget *widgetMain;
|
||||
QVBoxLayout *verticalLayout2;
|
||||
QLabel *labInfo;
|
||||
|
||||
QPropertyAnimation *animation;
|
||||
bool fullScreen;
|
||||
|
||||
private:
|
||||
int closeSec; //总显示时间
|
||||
int currentSec; //当前已显示时间
|
||||
|
||||
private slots:
|
||||
void initControl(); //初始化控件
|
||||
void initForm(); //初始化窗体
|
||||
void checkSec(); //校验倒计时
|
||||
|
||||
private slots:
|
||||
void on_btnMenu_Close_clicked();
|
||||
|
||||
public Q_SLOTS:
|
||||
void setIconMain(const QChar &str, quint32 size = 12);
|
||||
void setTip(const QString &title, const QString &tip, bool fullScreen = false, bool center = true, int closeSec = 0);
|
||||
void hide();
|
||||
};
|
||||
|
||||
|
||||
//弹出输入框类
|
||||
class QUIInputBox : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
static QUIInputBox *Instance();
|
||||
explicit QUIInputBox(QWidget *parent = 0);
|
||||
~QUIInputBox();
|
||||
|
||||
protected:
|
||||
void showEvent(QShowEvent *);
|
||||
void closeEvent(QCloseEvent *);
|
||||
bool eventFilter(QObject *watched, QEvent *event);
|
||||
|
||||
private:
|
||||
static QScopedPointer<QUIInputBox> self;
|
||||
|
||||
QVBoxLayout *verticalLayout1;
|
||||
QWidget *widgetTitle;
|
||||
QHBoxLayout *horizontalLayout1;
|
||||
QLabel *labIco;
|
||||
QLabel *labTitle;
|
||||
QLabel *labTime;
|
||||
QWidget *widgetMenu;
|
||||
QHBoxLayout *horizontalLayout2;
|
||||
QPushButton *btnMenu_Close;
|
||||
QWidget *widgetMain;
|
||||
QVBoxLayout *verticalLayout2;
|
||||
QFrame *frame;
|
||||
QVBoxLayout *verticalLayout3;
|
||||
QLabel *labInfo;
|
||||
QLineEdit *txtValue;
|
||||
QComboBox *cboxValue;
|
||||
QHBoxLayout *lay;
|
||||
QSpacerItem *horizontalSpacer;
|
||||
QPushButton *btnOk;
|
||||
QPushButton *btnCancel;
|
||||
|
||||
private:
|
||||
int closeSec; //总显示时间
|
||||
int currentSec; //当前已显示时间
|
||||
QString value; //当前值
|
||||
|
||||
private slots:
|
||||
void initControl(); //初始化控件
|
||||
void initForm(); //初始化窗体
|
||||
void checkSec(); //校验倒计时
|
||||
|
||||
private slots:
|
||||
void on_btnOk_clicked();
|
||||
void on_btnMenu_Close_clicked();
|
||||
|
||||
public:
|
||||
QString getValue()const;
|
||||
|
||||
public Q_SLOTS:
|
||||
void setIconMain(const QChar &str, quint32 size = 12);
|
||||
void setParameter(const QString &title, int type = 0, int closeSec = 0,
|
||||
QString placeholderText = QString(), bool pwd = false,
|
||||
const QString &defaultValue = QString());
|
||||
|
||||
};
|
||||
|
||||
//弹出日期选择对话框
|
||||
class QUIDateSelect : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
static QUIDateSelect *Instance();
|
||||
explicit QUIDateSelect(QWidget *parent = 0);
|
||||
~QUIDateSelect();
|
||||
|
||||
protected:
|
||||
bool eventFilter(QObject *watched, QEvent *event);
|
||||
|
||||
private:
|
||||
static QScopedPointer<QUIDateSelect> self;
|
||||
|
||||
QVBoxLayout *verticalLayout;
|
||||
QWidget *widgetTitle;
|
||||
QHBoxLayout *horizontalLayout1;
|
||||
QLabel *labIco;
|
||||
QLabel *labTitle;
|
||||
QWidget *widgetMenu;
|
||||
QHBoxLayout *horizontalLayout;
|
||||
QPushButton *btnMenu_Close;
|
||||
QWidget *widgetMain;
|
||||
QVBoxLayout *verticalLayout1;
|
||||
QFrame *frame;
|
||||
QGridLayout *gridLayout;
|
||||
QLabel *labStart;
|
||||
QPushButton *btnOk;
|
||||
QLabel *labEnd;
|
||||
QPushButton *btnClose;
|
||||
QDateTimeEdit *dateStart;
|
||||
QDateTimeEdit *dateEnd;
|
||||
|
||||
private:
|
||||
QString startDateTime; //开始时间
|
||||
QString endDateTime; //结束时间
|
||||
QString format; //日期时间格式
|
||||
|
||||
private slots:
|
||||
void initControl(); //初始化控件
|
||||
void initForm(); //初始化窗体
|
||||
|
||||
private slots:
|
||||
void on_btnOk_clicked();
|
||||
void on_btnMenu_Close_clicked();
|
||||
|
||||
public:
|
||||
//获取当前选择的开始时间和结束时间
|
||||
QString getStartDateTime() const;
|
||||
QString getEndDateTime() const;
|
||||
|
||||
public Q_SLOTS:
|
||||
void setIconMain(const QChar &str, quint32 size = 12);
|
||||
void setFormat(const QString &format);
|
||||
|
||||
};
|
||||
|
||||
//图形字体处理类
|
||||
class IconHelper : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
static IconHelper *Instance();
|
||||
explicit IconHelper(QObject *parent = 0);
|
||||
|
||||
//获取图形字体
|
||||
QFont getIconFont();
|
||||
|
||||
//设置图形字体到标签
|
||||
void setIcon(QLabel *lab, const QChar &str, quint32 size = 12);
|
||||
//设置图形字体到按钮
|
||||
void setIcon(QAbstractButton *btn, const QChar &str, quint32 size = 12);
|
||||
|
||||
//获取指定图形字体,可以指定文字大小,图片宽高,文字对齐
|
||||
QPixmap getPixmap(const QColor &color, const QChar &str, quint32 size = 12,
|
||||
quint32 pixWidth = 15, quint32 pixHeight = 15,
|
||||
int flags = Qt::AlignCenter);
|
||||
|
||||
//根据按钮获取该按钮对应的图标
|
||||
QPixmap getPixmap(QToolButton *btn, bool normal);
|
||||
QPixmap getPixmap(QToolButton *btn, int type);
|
||||
|
||||
//指定QFrame导航按钮样式,带图标
|
||||
void setStyle(QFrame *frame, QList<QToolButton *> btns, QList<int> pixChar,
|
||||
quint32 iconSize = 12, quint32 iconWidth = 15, quint32 iconHeight = 15,
|
||||
const QString &normalBgColor = "#2FC5A2",
|
||||
const QString &darkBgColor = "#3EA7E9",
|
||||
const QString &normalTextColor = "#EEEEEE",
|
||||
const QString &darkTextColor = "#FFFFFF");
|
||||
|
||||
//指定导航面板样式,不带图标
|
||||
static void setStyle(QWidget *widget, const QString &type = "left", int borderWidth = 3,
|
||||
const QString &borderColor = "#029FEA",
|
||||
const QString &normalBgColor = "#292F38",
|
||||
const QString &darkBgColor = "#1D2025",
|
||||
const QString &normalTextColor = "#54626F",
|
||||
const QString &darkTextColor = "#FDFDFD");
|
||||
|
||||
//移除导航面板样式,防止重复
|
||||
void removeStyle(QList<QToolButton *> btns);
|
||||
|
||||
//指定QWidget导航面板样式,带图标和效果切换
|
||||
void setStyle(QWidget *widget, QList<QToolButton *> btns, QList<int> pixChar,
|
||||
quint32 iconSize = 12, quint32 iconWidth = 15, quint32 iconHeight = 15,
|
||||
const QString &type = "left", int borderWidth = 3,
|
||||
const QString &borderColor = "#029FEA",
|
||||
const QString &normalBgColor = "#292F38",
|
||||
const QString &darkBgColor = "#1D2025",
|
||||
const QString &normalTextColor = "#54626F",
|
||||
const QString &darkTextColor = "#FDFDFD");
|
||||
|
||||
struct StyleColor {
|
||||
quint32 iconSize;
|
||||
quint32 iconWidth;
|
||||
quint32 iconHeight;
|
||||
quint32 borderWidth;
|
||||
QString type;
|
||||
QString borderColor;
|
||||
QString normalBgColor;
|
||||
QString normalTextColor;
|
||||
QString hoverBgColor;
|
||||
QString hoverTextColor;
|
||||
QString pressedBgColor;
|
||||
QString pressedTextColor;
|
||||
QString checkedBgColor;
|
||||
QString checkedTextColor;
|
||||
|
||||
StyleColor()
|
||||
{
|
||||
iconSize = 12;
|
||||
iconWidth = 15;
|
||||
iconHeight = 15;
|
||||
borderWidth = 3;
|
||||
type = "left";
|
||||
borderColor = "#029FEA";
|
||||
normalBgColor = "#292F38";
|
||||
normalTextColor = "#54626F";
|
||||
hoverBgColor = "#40444D";
|
||||
hoverTextColor = "#FDFDFD";
|
||||
pressedBgColor = "#404244";
|
||||
pressedTextColor = "#FDFDFD";
|
||||
checkedBgColor = "#44494F";
|
||||
checkedTextColor = "#FDFDFD";
|
||||
}
|
||||
};
|
||||
|
||||
//指定QWidget导航面板样式,带图标和效果切换+悬停颜色+按下颜色+选中颜色
|
||||
void setStyle(QWidget *widget, QList<QToolButton *> btns, QList<int> pixChar, const StyleColor &styleColor);
|
||||
|
||||
protected:
|
||||
bool eventFilter(QObject *watched, QEvent *event);
|
||||
|
||||
private:
|
||||
static QScopedPointer<IconHelper> self;
|
||||
|
||||
QFont iconFont; //图形字体
|
||||
QList<QToolButton *> btns; //按钮队列
|
||||
QList<QPixmap> pixNormal; //正常图片队列
|
||||
QList<QPixmap> pixDark; //加深图片队列
|
||||
QList<QPixmap> pixHover; //悬停图片队列
|
||||
QList<QPixmap> pixPressed; //按下图片队列
|
||||
QList<QPixmap> pixChecked; //选中图片队列
|
||||
};
|
||||
|
||||
//托盘图标类
|
||||
class TrayIcon : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
static TrayIcon *Instance();
|
||||
explicit TrayIcon(QObject *parent = 0);
|
||||
|
||||
private:
|
||||
static QScopedPointer<TrayIcon> self;
|
||||
|
||||
QWidget *mainWidget; //对应所属主窗体
|
||||
QSystemTrayIcon *trayIcon; //托盘对象
|
||||
QMenu *menu; //右键菜单
|
||||
bool exitDirect; //是否直接退出
|
||||
|
||||
private slots:
|
||||
void iconIsActived(QSystemTrayIcon::ActivationReason reason);
|
||||
|
||||
public Q_SLOTS:
|
||||
//设置是否直接退出,如果不是直接退出则发送信号给主界面
|
||||
void setExitDirect(bool exitDirect);
|
||||
|
||||
//设置所属主窗体
|
||||
void setMainWidget(QWidget *mainWidget);
|
||||
|
||||
//显示消息
|
||||
void showMessage(const QString &title, const QString &msg,
|
||||
QSystemTrayIcon::MessageIcon icon = QSystemTrayIcon::Information, int msecs = 5000);
|
||||
|
||||
//设置图标
|
||||
void setIcon(const QString &strIcon);
|
||||
//设置提示信息
|
||||
void setToolTip(const QString &tip);
|
||||
//设置是否可见
|
||||
void setVisible(bool visible);
|
||||
//退出所有
|
||||
void closeAll();
|
||||
|
||||
Q_SIGNALS:
|
||||
void trayIconExit();
|
||||
};
|
||||
|
||||
|
||||
//全局静态方法类
|
||||
class QUIHelper : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
//桌面宽度高度
|
||||
static int deskWidth();
|
||||
static int deskHeight();
|
||||
|
||||
//程序本身文件名称
|
||||
static QString appName();
|
||||
//程序当前所在路径
|
||||
static QString appPath();
|
||||
|
||||
//初始化随机数种子
|
||||
static void initRand();
|
||||
|
||||
//初始化数据库
|
||||
static void initDb(const QString &dbName);
|
||||
//初始化文件,不存在则拷贝
|
||||
static void initFile(const QString &sourceName, const QString &targetName);
|
||||
|
||||
//新建目录
|
||||
static void newDir(const QString &dirName);
|
||||
|
||||
//写入消息到额外的的消息日志文件
|
||||
static void writeInfo(const QString &info, const QString &filePath = "log");
|
||||
static void writeError(const QString &info, const QString &filePath = "log");
|
||||
|
||||
//设置全局样式
|
||||
static void setStyle(QUIWidget::Style style);
|
||||
static void setStyle(const QString &qssFile, QString &paletteColor, QString &textColor);
|
||||
static void setStyle(const QString &qssFile, QString &textColor,
|
||||
QString &panelColor, QString &borderColor,
|
||||
QString &normalColorStart, QString &normalColorEnd,
|
||||
QString &darkColorStart, QString &darkColorEnd,
|
||||
QString &highColor);
|
||||
|
||||
//根据QSS样式获取对应颜色值
|
||||
static void getQssColor(const QString &qss, QString &textColor,
|
||||
QString &panelColor, QString &borderColor,
|
||||
QString &normalColorStart, QString &normalColorEnd,
|
||||
QString &darkColorStart, QString &darkColorEnd,
|
||||
QString &highColor);
|
||||
|
||||
//九宫格图片 horzSplit-宫格1/3/7/9宽度 vertSplit-宫格1/3/7/9高度 dstWidth-目标图片宽度 dstHeight-目标图片高度
|
||||
static QPixmap ninePatch(const QString &picName, int horzSplit, int vertSplit, int dstWidth, int dstHeight);
|
||||
static QPixmap ninePatch(const QPixmap &pix, int horzSplit, int vertSplit, int dstWidth, int dstHeight);
|
||||
|
||||
//设置标签颜色
|
||||
static void setLabStyle(QLabel *lab, quint8 type);
|
||||
|
||||
//设置窗体居中显示
|
||||
static void setFormInCenter(QWidget *frm);
|
||||
//设置翻译文件
|
||||
static void setTranslator(const QString &qmFile = ":/image/qt_zh_CN.qm");
|
||||
//设置编码
|
||||
static void setCode();
|
||||
//设置延时
|
||||
static void sleep(int msec);
|
||||
//设置系统时间
|
||||
static void setSystemDateTime(const QString &year, const QString &month, const QString &day,
|
||||
const QString &hour, const QString &min, const QString &sec);
|
||||
//设置开机自启动
|
||||
static void runWithSystem(const QString &strName, const QString &strPath, bool autoRun = true);
|
||||
|
||||
//判断是否是IP地址
|
||||
static bool isIP(const QString &ip);
|
||||
|
||||
//判断是否是MAC地址
|
||||
static bool isMac(const QString &mac);
|
||||
|
||||
//判断是否是合法的电话号码
|
||||
static bool isTel(const QString &tel);
|
||||
|
||||
//判断是否是合法的邮箱地址
|
||||
static bool isEmail(const QString &email);
|
||||
|
||||
|
||||
//16进制字符串转10进制
|
||||
static int strHexToDecimal(const QString &strHex);
|
||||
|
||||
//10进制字符串转10进制
|
||||
static int strDecimalToDecimal(const QString &strDecimal);
|
||||
|
||||
//2进制字符串转10进制
|
||||
static int strBinToDecimal(const QString &strBin);
|
||||
|
||||
//16进制字符串转2进制字符串
|
||||
static QString strHexToStrBin(const QString &strHex);
|
||||
|
||||
//10进制转2进制字符串一个字节
|
||||
static QString decimalToStrBin1(int decimal);
|
||||
|
||||
//10进制转2进制字符串两个字节
|
||||
static QString decimalToStrBin2(int decimal);
|
||||
|
||||
//10进制转16进制字符串,补零.
|
||||
static QString decimalToStrHex(int decimal);
|
||||
|
||||
|
||||
//int转字节数组
|
||||
static QByteArray intToByte(int i);
|
||||
static QByteArray intToByteRec(int i);
|
||||
|
||||
//字节数组转int
|
||||
static int byteToInt(const QByteArray &data);
|
||||
static int byteToIntRec(const QByteArray &data);
|
||||
static quint32 byteToUInt(const QByteArray &data);
|
||||
static quint32 byteToUIntRec(const QByteArray &data);
|
||||
|
||||
//ushort转字节数组
|
||||
static QByteArray ushortToByte(ushort i);
|
||||
static QByteArray ushortToByteRec(ushort i);
|
||||
|
||||
//字节数组转ushort
|
||||
static int byteToUShort(const QByteArray &data);
|
||||
static int byteToUShortRec(const QByteArray &data);
|
||||
|
||||
//异或加密算法
|
||||
static QString getXorEncryptDecrypt(const QString &str, char key);
|
||||
|
||||
//异或校验
|
||||
static uchar getOrCode(const QByteArray &data);
|
||||
|
||||
//计算校验码
|
||||
static uchar getCheckCode(const QByteArray &data);
|
||||
|
||||
//字符串补全
|
||||
static QString getValue(quint8 value);
|
||||
|
||||
//CRC校验
|
||||
static quint16 getRevCrc_16(quint8 *data, int len, quint16 init, const quint16 *table);
|
||||
static quint16 getCrc_16(quint8 *data, int len, quint16 init, const quint16 *table);
|
||||
static quint16 getModbus16(quint8 *data, int len);
|
||||
static QByteArray getCRCCode(const QByteArray &data);
|
||||
|
||||
|
||||
//字节数组转Ascii字符串
|
||||
static QString byteArrayToAsciiStr(const QByteArray &data);
|
||||
|
||||
//16进制字符串转字节数组
|
||||
static QByteArray hexStrToByteArray(const QString &str);
|
||||
static char convertHexChar(char ch);
|
||||
|
||||
//Ascii字符串转字节数组
|
||||
static QByteArray asciiStrToByteArray(const QString &str);
|
||||
|
||||
//字节数组转16进制字符串
|
||||
static QString byteArrayToHexStr(const QByteArray &data);
|
||||
|
||||
//获取保存的文件
|
||||
static QString getSaveName(const QString &filter, QString defaultDir = QCoreApplication::applicationDirPath());
|
||||
|
||||
//获取选择的文件
|
||||
static QString getFileName(const QString &filter, QString defaultDir = QCoreApplication::applicationDirPath());
|
||||
|
||||
//获取选择的文件集合
|
||||
static QStringList getFileNames(const QString &filter, QString defaultDir = QCoreApplication::applicationDirPath());
|
||||
|
||||
//获取选择的目录
|
||||
static QString getFolderName();
|
||||
|
||||
//获取文件名,含拓展名
|
||||
static QString getFileNameWithExtension(const QString &strFilePath);
|
||||
|
||||
//获取选择文件夹中的文件
|
||||
static QStringList getFolderFileNames(const QStringList &filter);
|
||||
|
||||
//文件夹是否存在
|
||||
static bool folderIsExist(const QString &strFolder);
|
||||
|
||||
//文件是否存在
|
||||
static bool fileIsExist(const QString &strFile);
|
||||
|
||||
//复制文件
|
||||
static bool copyFile(const QString &sourceFile, const QString &targetFile);
|
||||
|
||||
//删除文件夹下所有文件
|
||||
static void deleteDirectory(const QString &path);
|
||||
|
||||
//判断IP地址及端口是否在线
|
||||
static bool ipLive(const QString &ip, int port, int timeout = 1000);
|
||||
|
||||
//获取网页所有源代码
|
||||
static QString getHtml(const QString &url);
|
||||
|
||||
//获取本机公网IP地址
|
||||
static QString getNetIP(const QString &webCode);
|
||||
|
||||
//获取本机IP
|
||||
static QString getLocalIP();
|
||||
|
||||
//Url地址转为IP地址
|
||||
static QString urlToIP(const QString &url);
|
||||
|
||||
//判断是否通外网
|
||||
static bool isWebOk();
|
||||
|
||||
|
||||
//弹出消息框
|
||||
static void showMessageBoxInfo(const QString &info, int closeSec = 0, bool exec = false);
|
||||
//弹出错误框
|
||||
static void showMessageBoxError(const QString &info, int closeSec = 0, bool exec = false);
|
||||
//弹出询问框
|
||||
static int showMessageBoxQuestion(const QString &info);
|
||||
|
||||
//弹出+隐藏右下角信息框
|
||||
static void showTipBox(const QString &title, const QString &tip, bool fullScreen = false,
|
||||
bool center = true, int closeSec = 0);
|
||||
static void hideTipBox();
|
||||
|
||||
//弹出输入框
|
||||
static QString showInputBox(const QString &title, int type = 0, int closeSec = 0,
|
||||
const QString &placeholderText = QString(), bool pwd = false,
|
||||
const QString &defaultValue = QString());
|
||||
|
||||
//弹出日期选择框
|
||||
static void showDateSelect(QString &dateStart, QString &dateEnd, const QString &format = "yyyy-MM-dd");
|
||||
|
||||
|
||||
//设置按钮样式
|
||||
static QString setPushButtonQss(QPushButton *btn, //按钮对象
|
||||
int radius = 5, //圆角半径
|
||||
int padding = 8, //间距
|
||||
const QString &normalColor = "#34495E", //正常颜色
|
||||
const QString &normalTextColor = "#FFFFFF", //文字颜色
|
||||
const QString &hoverColor = "#4E6D8C", //悬停颜色
|
||||
const QString &hoverTextColor = "#F0F0F0", //悬停文字颜色
|
||||
const QString &pressedColor = "#2D3E50", //按下颜色
|
||||
const QString &pressedTextColor = "#B8C6D1"); //按下文字颜色
|
||||
|
||||
//设置文本框样式
|
||||
static QString setLineEditQss(QLineEdit *txt, //文本框对象
|
||||
int radius = 3, //圆角半径
|
||||
int borderWidth = 2, //边框大小
|
||||
const QString &normalColor = "#DCE4EC", //正常颜色
|
||||
const QString &focusColor = "#34495E"); //选中颜色
|
||||
|
||||
//设置进度条样式
|
||||
static QString setProgressBarQss(QProgressBar *bar,
|
||||
int barHeight = 8, //进度条高度
|
||||
int barRadius = 5, //进度条半径
|
||||
int fontSize = 9, //文字字号
|
||||
const QString &normalColor = "#E8EDF2", //正常颜色
|
||||
const QString &chunkColor = "#E74C3C"); //进度颜色
|
||||
|
||||
//设置滑块条样式
|
||||
static QString setSliderQss(QSlider *slider, //滑动条对象
|
||||
int sliderHeight = 8, //滑动条高度
|
||||
const QString &normalColor = "#E8EDF2", //正常颜色
|
||||
const QString &grooveColor = "#1ABC9C", //滑块颜色
|
||||
const QString &handleBorderColor = "#1ABC9C", //指示器边框颜色
|
||||
const QString &handleColor = "#FFFFFF", //指示器颜色
|
||||
const QString &textColor = "#000000"); //文字颜色
|
||||
|
||||
//设置单选框样式
|
||||
static QString setRadioButtonQss(QRadioButton *rbtn, //单选框对象
|
||||
int indicatorRadius = 8, //指示器圆角角度
|
||||
const QString &normalColor = "#D7DBDE", //正常颜色
|
||||
const QString &checkColor = "#34495E"); //选中颜色
|
||||
|
||||
//设置滚动条样式
|
||||
static QString setScrollBarQss(QWidget *scroll, //滚动条对象
|
||||
int radius = 6, //圆角角度
|
||||
int min = 120, //指示器最小长度
|
||||
int max = 12, //滚动条最大长度
|
||||
const QString &bgColor = "#606060", //背景色
|
||||
const QString &handleNormalColor = "#34495E", //指示器正常颜色
|
||||
const QString &handleHoverColor = "#1ABC9C", //指示器悬停颜色
|
||||
const QString &handlePressedColor = "#E74C3C"); //指示器按下颜色
|
||||
};
|
||||
|
||||
//全局变量控制
|
||||
class QUIConfig
|
||||
{
|
||||
public:
|
||||
//全局图标
|
||||
static QChar IconMain; //标题栏左上角图标
|
||||
static QChar IconMenu; //下拉菜单图标
|
||||
static QChar IconMin; //最小化图标
|
||||
static QChar IconMax; //最大化图标
|
||||
static QChar IconNormal; //还原图标
|
||||
static QChar IconClose; //关闭图标
|
||||
|
||||
static QString FontName; //全局字体名称
|
||||
static int FontSize; //全局字体大小
|
||||
|
||||
//样式表颜色值
|
||||
static QString TextColor; //文字颜色
|
||||
static QString PanelColor; //面板颜色
|
||||
static QString BorderColor; //边框颜色
|
||||
static QString NormalColorStart;//正常状态开始颜色
|
||||
static QString NormalColorEnd; //正常状态结束颜色
|
||||
static QString DarkColorStart; //加深状态开始颜色
|
||||
static QString DarkColorEnd; //加深状态结束颜色
|
||||
static QString HighColor; //高亮颜色
|
||||
};
|
||||
|
||||
#endif // QUIWIDGET_H
|
|
@ -0,0 +1,36 @@
|
|||
#-------------------------------------------------
|
||||
#
|
||||
# Project created by QtCreator 2016-09-19T22:25:56
|
||||
#
|
||||
#-------------------------------------------------
|
||||
|
||||
QT += core gui network
|
||||
|
||||
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
|
||||
|
||||
TARGET = comtool
|
||||
TEMPLATE = app
|
||||
MOC_DIR = temp/moc
|
||||
RCC_DIR = temp/rcc
|
||||
UI_DIR = temp/ui
|
||||
OBJECTS_DIR = temp/obj
|
||||
DESTDIR = bin
|
||||
RC_FILE = other/main.rc
|
||||
|
||||
SOURCES += main.cpp
|
||||
HEADERS += head.h
|
||||
RESOURCES += other/main.qrc
|
||||
CONFIG += warn_off
|
||||
|
||||
include ($$PWD/api/api.pri)
|
||||
include ($$PWD/form/form.pri)
|
||||
include ($$PWD/qextserialport/qextserialport.pri)
|
||||
|
||||
INCLUDEPATH += $$PWD
|
||||
INCLUDEPATH += $$PWD/api
|
||||
INCLUDEPATH += $$PWD/form
|
||||
INCLUDEPATH += $$PWD/qextserialport
|
||||
|
||||
#INCLUDEPATH += /usr/local/openssl-1.0.2m-h3-gcc-4.9.2/include
|
||||
#LIBS += -L/usr/local/openssl-1.0.2m-h3-gcc-4.9.2/lib -lssl -lcrypto
|
||||
#LIBS += -L/usr/local/h3_rootfsv -lXdmcp
|
|
@ -0,0 +1 @@
|
|||
01 03 00 00 00 06 C5 C8;01 03 0C 00 01 00 01 00 00 00 01 00 01 00 01 37 DC
|
|
@ -0,0 +1,17 @@
|
|||
16 FF 01 01 E0 E1
|
||||
16 FF 01 01 E1 E2
|
||||
16 01 02 DF BC 16 01 02 DF BC 16 01 02 DF BC 12 13 14 15
|
||||
16 00 00 04 D0 F0 F1 65 C4
|
||||
16 00 00 04 D0 05 AB 5A C4
|
||||
16 01 10 02 F0 03 06 16 01 11 02 F0 03 06 16 01 12 02 F0 03 06 16 01 13 02 F0 03 06 16 01
|
||||
14 02 F0 03 06 16 01 15 02 F0 03 06 16 01 16 02 F0 03 06
|
||||
16 11 01 03 E8 01 10 0E
|
||||
16 11 01 03 E8 01 12 10
|
||||
16 11 01 03 E8 01 14 12
|
||||
16 11 01 03 E8 01 15 13
|
||||
DISARMEDALL
|
||||
BURGLARY 012
|
||||
BYPASS 012
|
||||
DISARMED 012
|
||||
16 00 01 01 D1 D3
|
||||
16 01 11 11
|
|
@ -0,0 +1,8 @@
|
|||
FORMS += \
|
||||
$$PWD/frmcomtool.ui
|
||||
|
||||
HEADERS += \
|
||||
$$PWD/frmcomtool.h
|
||||
|
||||
SOURCES += \
|
||||
$$PWD/frmcomtool.cpp
|
|
@ -0,0 +1,584 @@
|
|||
#include "frmcomtool.h"
|
||||
#include "ui_frmcomtool.h"
|
||||
#include "quiwidget.h"
|
||||
|
||||
frmComTool::frmComTool(QWidget *parent) : QWidget(parent), ui(new Ui::frmComTool)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
this->initForm();
|
||||
this->initConfig();
|
||||
QUIHelper::setFormInCenter(this);
|
||||
}
|
||||
|
||||
frmComTool::~frmComTool()
|
||||
{
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void frmComTool::initForm()
|
||||
{
|
||||
comOk = false;
|
||||
com = 0;
|
||||
sleepTime = 10;
|
||||
receiveCount = 0;
|
||||
sendCount = 0;
|
||||
isShow = true;
|
||||
|
||||
ui->cboxSendInterval->addItems(App::Intervals);
|
||||
ui->cboxData->addItems(App::Datas);
|
||||
|
||||
//读取数据
|
||||
timerRead = new QTimer(this);
|
||||
timerRead->setInterval(100);
|
||||
connect(timerRead, SIGNAL(timeout()), this, SLOT(readData()));
|
||||
|
||||
//发送数据
|
||||
timerSend = new QTimer(this);
|
||||
connect(timerSend, SIGNAL(timeout()), this, SLOT(sendData()));
|
||||
connect(ui->btnSend, SIGNAL(clicked()), this, SLOT(sendData()));
|
||||
|
||||
//保存数据
|
||||
timerSave = new QTimer(this);
|
||||
connect(timerSave, SIGNAL(timeout()), this, SLOT(saveData()));
|
||||
connect(ui->btnSave, SIGNAL(clicked()), this, SLOT(saveData()));
|
||||
|
||||
ui->tabWidget->setCurrentIndex(0);
|
||||
changeEnable(false);
|
||||
|
||||
tcpOk = false;
|
||||
socket = new QTcpSocket(this);
|
||||
socket->abort();
|
||||
connect(socket, SIGNAL(readyRead()), this, SLOT(readDataNet()));
|
||||
connect(socket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(readErrorNet()));
|
||||
|
||||
timerConnect = new QTimer(this);
|
||||
connect(timerConnect, SIGNAL(timeout()), this, SLOT(connectNet()));
|
||||
timerConnect->setInterval(3000);
|
||||
timerConnect->start();
|
||||
|
||||
#ifdef __arm__
|
||||
ui->widgetRight->setFixedWidth(280);
|
||||
#endif
|
||||
}
|
||||
|
||||
void frmComTool::initConfig()
|
||||
{
|
||||
QStringList comList;
|
||||
for (int i = 1; i <= 20; i++) {
|
||||
comList << QString("COM%1").arg(i);
|
||||
}
|
||||
|
||||
comList << "ttyUSB0" << "ttyS0" << "ttyS1" << "ttyS2" << "ttyS3" << "ttyS4";
|
||||
comList << "ttymxc1" << "ttymxc2" << "ttymxc3" << "ttymxc4";
|
||||
comList << "ttySAC1" << "ttySAC2" << "ttySAC3" << "ttySAC4";
|
||||
ui->cboxPortName->addItems(comList);
|
||||
ui->cboxPortName->setCurrentIndex(ui->cboxPortName->findText(App::PortName));
|
||||
connect(ui->cboxPortName, SIGNAL(currentIndexChanged(int)), this, SLOT(saveConfig()));
|
||||
|
||||
QStringList baudList;
|
||||
baudList << "50" << "75" << "100" << "134" << "150" << "200" << "300" << "600" << "1200"
|
||||
<< "1800" << "2400" << "4800" << "9600" << "14400" << "19200" << "38400"
|
||||
<< "56000" << "57600" << "76800" << "115200" << "128000" << "256000";
|
||||
|
||||
ui->cboxBaudRate->addItems(baudList);
|
||||
ui->cboxBaudRate->setCurrentIndex(ui->cboxBaudRate->findText(QString::number(App::BaudRate)));
|
||||
connect(ui->cboxBaudRate, SIGNAL(currentIndexChanged(int)), this, SLOT(saveConfig()));
|
||||
|
||||
QStringList dataBitsList;
|
||||
dataBitsList << "5" << "6" << "7" << "8";
|
||||
|
||||
ui->cboxDataBit->addItems(dataBitsList);
|
||||
ui->cboxDataBit->setCurrentIndex(ui->cboxDataBit->findText(QString::number(App::DataBit)));
|
||||
connect(ui->cboxDataBit, SIGNAL(currentIndexChanged(int)), this, SLOT(saveConfig()));
|
||||
|
||||
QStringList parityList;
|
||||
parityList << "无" << "奇" << "偶";
|
||||
#ifdef Q_OS_WIN
|
||||
parityList << "标志";
|
||||
#endif
|
||||
parityList << "空格";
|
||||
|
||||
ui->cboxParity->addItems(parityList);
|
||||
ui->cboxParity->setCurrentIndex(ui->cboxParity->findText(App::Parity));
|
||||
connect(ui->cboxParity, SIGNAL(currentIndexChanged(int)), this, SLOT(saveConfig()));
|
||||
|
||||
QStringList stopBitsList;
|
||||
stopBitsList << "1";
|
||||
#ifdef Q_OS_WIN
|
||||
stopBitsList << "1.5";
|
||||
#endif
|
||||
stopBitsList << "2";
|
||||
|
||||
ui->cboxStopBit->addItems(stopBitsList);
|
||||
ui->cboxStopBit->setCurrentIndex(ui->cboxStopBit->findText(QString::number(App::StopBit)));
|
||||
connect(ui->cboxStopBit, SIGNAL(currentIndexChanged(int)), this, SLOT(saveConfig()));
|
||||
|
||||
ui->ckHexSend->setChecked(App::HexSend);
|
||||
connect(ui->ckHexSend, SIGNAL(stateChanged(int)), this, SLOT(saveConfig()));
|
||||
|
||||
ui->ckHexReceive->setChecked(App::HexReceive);
|
||||
connect(ui->ckHexReceive, SIGNAL(stateChanged(int)), this, SLOT(saveConfig()));
|
||||
|
||||
ui->ckDebug->setChecked(App::Debug);
|
||||
connect(ui->ckDebug, SIGNAL(stateChanged(int)), this, SLOT(saveConfig()));
|
||||
|
||||
ui->ckAutoClear->setChecked(App::AutoClear);
|
||||
connect(ui->ckAutoClear, SIGNAL(stateChanged(int)), this, SLOT(saveConfig()));
|
||||
|
||||
ui->ckAutoSend->setChecked(App::AutoSend);
|
||||
connect(ui->ckAutoSend, SIGNAL(stateChanged(int)), this, SLOT(saveConfig()));
|
||||
|
||||
ui->ckAutoSave->setChecked(App::AutoSave);
|
||||
connect(ui->ckAutoSave, SIGNAL(stateChanged(int)), this, SLOT(saveConfig()));
|
||||
|
||||
QStringList sendInterval;
|
||||
QStringList saveInterval;
|
||||
sendInterval << "100" << "300" << "500";
|
||||
|
||||
for (int i = 1000; i <= 10000; i = i + 1000) {
|
||||
sendInterval << QString::number(i);
|
||||
saveInterval << QString::number(i);
|
||||
}
|
||||
|
||||
ui->cboxSendInterval->addItems(sendInterval);
|
||||
ui->cboxSaveInterval->addItems(saveInterval);
|
||||
|
||||
ui->cboxSendInterval->setCurrentIndex(ui->cboxSendInterval->findText(QString::number(App::SendInterval)));
|
||||
connect(ui->cboxSendInterval, SIGNAL(currentIndexChanged(int)), this, SLOT(saveConfig()));
|
||||
ui->cboxSaveInterval->setCurrentIndex(ui->cboxSaveInterval->findText(QString::number(App::SaveInterval)));
|
||||
connect(ui->cboxSaveInterval, SIGNAL(currentIndexChanged(int)), this, SLOT(saveConfig()));
|
||||
|
||||
timerSend->setInterval(App::SendInterval);
|
||||
timerSave->setInterval(App::SaveInterval);
|
||||
|
||||
if (App::AutoSend) {
|
||||
timerSend->start();
|
||||
}
|
||||
|
||||
if (App::AutoSave) {
|
||||
timerSave->start();
|
||||
}
|
||||
|
||||
//串口转网络部分
|
||||
ui->cboxMode->setCurrentIndex(ui->cboxMode->findText(App::Mode));
|
||||
connect(ui->cboxMode, SIGNAL(currentIndexChanged(int)), this, SLOT(saveConfig()));
|
||||
|
||||
ui->txtServerIP->setText(App::ServerIP);
|
||||
connect(ui->txtServerIP, SIGNAL(textChanged(QString)), this, SLOT(saveConfig()));
|
||||
|
||||
ui->txtServerPort->setText(QString::number(App::ServerPort));
|
||||
connect(ui->txtServerPort, SIGNAL(textChanged(QString)), this, SLOT(saveConfig()));
|
||||
|
||||
ui->txtListenPort->setText(QString::number(App::ListenPort));
|
||||
connect(ui->txtListenPort, SIGNAL(textChanged(QString)), this, SLOT(saveConfig()));
|
||||
|
||||
QStringList values;
|
||||
values << "0" << "10" << "50";
|
||||
|
||||
for (int i = 100; i < 1000; i = i + 100) {
|
||||
values << QString("%1").arg(i);
|
||||
}
|
||||
|
||||
ui->cboxSleepTime->addItems(values);
|
||||
|
||||
ui->cboxSleepTime->setCurrentIndex(ui->cboxSleepTime->findText(QString::number(App::SleepTime)));
|
||||
connect(ui->cboxSleepTime, SIGNAL(currentIndexChanged(int)), this, SLOT(saveConfig()));
|
||||
|
||||
ui->ckAutoConnect->setChecked(App::AutoConnect);
|
||||
connect(ui->ckAutoConnect, SIGNAL(stateChanged(int)), this, SLOT(saveConfig()));
|
||||
}
|
||||
|
||||
void frmComTool::saveConfig()
|
||||
{
|
||||
App::PortName = ui->cboxPortName->currentText();
|
||||
App::BaudRate = ui->cboxBaudRate->currentText().toInt();
|
||||
App::DataBit = ui->cboxDataBit->currentText().toInt();
|
||||
App::Parity = ui->cboxParity->currentText();
|
||||
App::StopBit = ui->cboxStopBit->currentText().toDouble();
|
||||
|
||||
App::HexSend = ui->ckHexSend->isChecked();
|
||||
App::HexReceive = ui->ckHexReceive->isChecked();
|
||||
App::Debug = ui->ckDebug->isChecked();
|
||||
App::AutoClear = ui->ckAutoClear->isChecked();
|
||||
|
||||
App::AutoSend = ui->ckAutoSend->isChecked();
|
||||
App::AutoSave = ui->ckAutoSave->isChecked();
|
||||
|
||||
int sendInterval = ui->cboxSendInterval->currentText().toInt();
|
||||
if (sendInterval != App::SendInterval) {
|
||||
App::SendInterval = sendInterval;
|
||||
timerSend->setInterval(App::SendInterval);
|
||||
}
|
||||
|
||||
int saveInterval = ui->cboxSaveInterval->currentText().toInt();
|
||||
if (saveInterval != App::SaveInterval) {
|
||||
App::SaveInterval = saveInterval;
|
||||
timerSave->setInterval(App::SaveInterval);
|
||||
}
|
||||
|
||||
App::Mode = ui->cboxMode->currentText();
|
||||
App::ServerIP = ui->txtServerIP->text().trimmed();
|
||||
App::ServerPort = ui->txtServerPort->text().toInt();
|
||||
App::ListenPort = ui->txtListenPort->text().toInt();
|
||||
App::SleepTime = ui->cboxSleepTime->currentText().toInt();
|
||||
App::AutoConnect = ui->ckAutoConnect->isChecked();
|
||||
|
||||
App::writeConfig();
|
||||
}
|
||||
|
||||
void frmComTool::changeEnable(bool b)
|
||||
{
|
||||
ui->cboxBaudRate->setEnabled(!b);
|
||||
ui->cboxDataBit->setEnabled(!b);
|
||||
ui->cboxParity->setEnabled(!b);
|
||||
ui->cboxPortName->setEnabled(!b);
|
||||
ui->cboxStopBit->setEnabled(!b);
|
||||
ui->btnSend->setEnabled(b);
|
||||
ui->ckAutoSend->setEnabled(b);
|
||||
ui->ckAutoSave->setEnabled(b);
|
||||
}
|
||||
|
||||
void frmComTool::append(int type, const QString &data, bool clear)
|
||||
{
|
||||
static int currentCount = 0;
|
||||
static int maxCount = 100;
|
||||
|
||||
if (clear) {
|
||||
ui->txtMain->clear();
|
||||
currentCount = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
if (currentCount >= maxCount) {
|
||||
ui->txtMain->clear();
|
||||
currentCount = 0;
|
||||
}
|
||||
|
||||
if (!isShow) {
|
||||
return;
|
||||
}
|
||||
|
||||
//过滤回车换行符
|
||||
QString strData = data;
|
||||
strData = strData.replace("\r", "");
|
||||
strData = strData.replace("\n", "");
|
||||
|
||||
//不同类型不同颜色显示
|
||||
QString strType;
|
||||
if (type == 0) {
|
||||
strType = "串口发送 >>";
|
||||
ui->txtMain->setTextColor(QColor("dodgerblue"));
|
||||
} else if (type == 1) {
|
||||
strType = "串口接收 <<";
|
||||
ui->txtMain->setTextColor(QColor("red"));
|
||||
} else if (type == 2) {
|
||||
strType = "处理延时 >>";
|
||||
ui->txtMain->setTextColor(QColor("gray"));
|
||||
} else if (type == 3) {
|
||||
strType = "正在校验 >>";
|
||||
ui->txtMain->setTextColor(QColor("green"));
|
||||
} else if (type == 4) {
|
||||
strType = "网络发送 >>";
|
||||
ui->txtMain->setTextColor(QColor(24, 189, 155));
|
||||
} else if (type == 5) {
|
||||
strType = "网络接收 <<";
|
||||
ui->txtMain->setTextColor(QColor(255, 107, 107));
|
||||
} else if (type == 6) {
|
||||
strType = "提示信息 >>";
|
||||
ui->txtMain->setTextColor(QColor(100, 184, 255));
|
||||
}
|
||||
|
||||
strData = QString("时间[%1] %2 %3").arg(TIMEMS).arg(strType).arg(strData);
|
||||
ui->txtMain->append(strData);
|
||||
currentCount++;
|
||||
}
|
||||
|
||||
void frmComTool::readData()
|
||||
{
|
||||
if (com->bytesAvailable() <= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
QUIHelper::sleep(sleepTime);
|
||||
QByteArray data = com->readAll();
|
||||
int dataLen = data.length();
|
||||
if (dataLen <= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (isShow) {
|
||||
QString buffer;
|
||||
if (ui->ckHexReceive->isChecked()) {
|
||||
buffer = QUIHelper::byteArrayToHexStr(data);
|
||||
} else {
|
||||
//buffer = QUIHelper::byteArrayToAsciiStr(data);
|
||||
buffer = QString::fromLocal8Bit(data);
|
||||
}
|
||||
|
||||
//启用调试则模拟调试数据
|
||||
if (ui->ckDebug->isChecked()) {
|
||||
int count = App::Keys.count();
|
||||
for (int i = 0; i < count; i++) {
|
||||
if (buffer.startsWith(App::Keys.at(i))) {
|
||||
sendData(App::Values.at(i));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
append(1, buffer);
|
||||
receiveCount = receiveCount + data.size();
|
||||
ui->btnReceiveCount->setText(QString("接收 : %1 字节").arg(receiveCount));
|
||||
|
||||
//启用网络转发则调用网络发送数据
|
||||
if (tcpOk) {
|
||||
socket->write(data);
|
||||
append(4, QString(buffer));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void frmComTool::sendData()
|
||||
{
|
||||
QString str = ui->cboxData->currentText();
|
||||
if (str.isEmpty()) {
|
||||
ui->cboxData->setFocus();
|
||||
return;
|
||||
}
|
||||
|
||||
sendData(str);
|
||||
|
||||
if (ui->ckAutoClear->isChecked()) {
|
||||
ui->cboxData->setCurrentIndex(-1);
|
||||
ui->cboxData->setFocus();
|
||||
}
|
||||
}
|
||||
|
||||
void frmComTool::sendData(QString data)
|
||||
{
|
||||
if (com == 0 || !com->isOpen()) {
|
||||
return;
|
||||
}
|
||||
|
||||
//短信猫调试
|
||||
if (data.startsWith("AT")) {
|
||||
data += "\r";
|
||||
}
|
||||
|
||||
QByteArray buffer;
|
||||
|
||||
if (ui->ckHexSend->isChecked()) {
|
||||
buffer = QUIHelper::hexStrToByteArray(data);
|
||||
} else {
|
||||
buffer = QUIHelper::asciiStrToByteArray(data);
|
||||
}
|
||||
|
||||
com->write(buffer);
|
||||
append(0, data);
|
||||
sendCount = sendCount + buffer.size();
|
||||
ui->btnSendCount->setText(QString("发送 : %1 字节").arg(sendCount));
|
||||
}
|
||||
|
||||
void frmComTool::saveData()
|
||||
{
|
||||
QString tempData = ui->txtMain->toPlainText();
|
||||
|
||||
if (tempData == "") {
|
||||
return;
|
||||
}
|
||||
|
||||
QDateTime now = QDateTime::currentDateTime();
|
||||
QString name = now.toString("yyyy-MM-dd-HH-mm-ss");
|
||||
QString fileName = QString("%1/%2.txt").arg(QUIHelper::appPath()).arg(name);
|
||||
|
||||
QFile file(fileName);
|
||||
file.open(QFile::WriteOnly | QIODevice::Text);
|
||||
QTextStream out(&file);
|
||||
out << tempData;
|
||||
file.close();
|
||||
|
||||
on_btnClear_clicked();
|
||||
}
|
||||
|
||||
void frmComTool::on_btnOpen_clicked()
|
||||
{
|
||||
if (ui->btnOpen->text() == "打开串口") {
|
||||
com = new QextSerialPort(ui->cboxPortName->currentText(), QextSerialPort::Polling);
|
||||
comOk = com->open(QIODevice::ReadWrite);
|
||||
|
||||
if (comOk) {
|
||||
//清空缓冲区
|
||||
com->flush();
|
||||
//设置波特率
|
||||
com->setBaudRate((BaudRateType)ui->cboxBaudRate->currentText().toInt());
|
||||
//设置数据位
|
||||
com->setDataBits((DataBitsType)ui->cboxDataBit->currentText().toInt());
|
||||
//设置校验位
|
||||
com->setParity((ParityType)ui->cboxParity->currentIndex());
|
||||
//设置停止位
|
||||
com->setStopBits((StopBitsType)ui->cboxStopBit->currentIndex());
|
||||
com->setFlowControl(FLOW_OFF);
|
||||
com->setTimeout(10);
|
||||
|
||||
changeEnable(true);
|
||||
ui->btnOpen->setText("关闭串口");
|
||||
timerRead->start();
|
||||
}
|
||||
} else {
|
||||
timerRead->stop();
|
||||
com->close();
|
||||
com->deleteLater();
|
||||
|
||||
changeEnable(false);
|
||||
ui->btnOpen->setText("打开串口");
|
||||
on_btnClear_clicked();
|
||||
comOk = false;
|
||||
}
|
||||
}
|
||||
|
||||
void frmComTool::on_btnSendCount_clicked()
|
||||
{
|
||||
sendCount = 0;
|
||||
ui->btnSendCount->setText("发送 : 0 字节");
|
||||
}
|
||||
|
||||
void frmComTool::on_btnReceiveCount_clicked()
|
||||
{
|
||||
receiveCount = 0;
|
||||
ui->btnReceiveCount->setText("接收 : 0 字节");
|
||||
}
|
||||
|
||||
void frmComTool::on_btnStopShow_clicked()
|
||||
{
|
||||
if (ui->btnStopShow->text() == "停止显示") {
|
||||
isShow = false;
|
||||
ui->btnStopShow->setText("开始显示");
|
||||
} else {
|
||||
isShow = true;
|
||||
ui->btnStopShow->setText("停止显示");
|
||||
}
|
||||
}
|
||||
|
||||
void frmComTool::on_btnData_clicked()
|
||||
{
|
||||
QString fileName = QString("%1/%2").arg(QUIHelper::appPath()).arg("send.txt");
|
||||
QFile file(fileName);
|
||||
if (!file.exists()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (ui->btnData->text() == "管理数据") {
|
||||
ui->txtMain->setReadOnly(false);
|
||||
ui->txtMain->clear();
|
||||
file.open(QFile::ReadOnly | QIODevice::Text);
|
||||
QTextStream in(&file);
|
||||
ui->txtMain->setText(in.readAll());
|
||||
file.close();
|
||||
ui->btnData->setText("保存数据");
|
||||
} else {
|
||||
ui->txtMain->setReadOnly(true);
|
||||
file.open(QFile::WriteOnly | QIODevice::Text);
|
||||
QTextStream out(&file);
|
||||
out << ui->txtMain->toPlainText();
|
||||
file.close();
|
||||
ui->txtMain->clear();
|
||||
ui->btnData->setText("管理数据");
|
||||
App::readSendData();
|
||||
}
|
||||
}
|
||||
|
||||
void frmComTool::on_btnClear_clicked()
|
||||
{
|
||||
append(0, "", true);
|
||||
}
|
||||
|
||||
void frmComTool::on_btnStart_clicked()
|
||||
{
|
||||
if (ui->btnStart->text() == "启动") {
|
||||
if (App::ServerIP == "" || App::ServerPort == 0) {
|
||||
append(6, "IP地址和远程端口不能为空");
|
||||
return;
|
||||
}
|
||||
|
||||
socket->connectToHost(App::ServerIP, App::ServerPort);
|
||||
if (socket->waitForConnected(100)) {
|
||||
ui->btnStart->setText("停止");
|
||||
append(6, "连接服务器成功");
|
||||
tcpOk = true;
|
||||
}
|
||||
} else {
|
||||
socket->disconnectFromHost();
|
||||
if (socket->state() == QAbstractSocket::UnconnectedState || socket->waitForDisconnected(100)) {
|
||||
ui->btnStart->setText("启动");
|
||||
append(6, "断开服务器成功");
|
||||
tcpOk = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void frmComTool::on_ckAutoSend_stateChanged(int arg1)
|
||||
{
|
||||
if (arg1 == 0) {
|
||||
ui->cboxSendInterval->setEnabled(false);
|
||||
timerSend->stop();
|
||||
} else {
|
||||
ui->cboxSendInterval->setEnabled(true);
|
||||
timerSend->start();
|
||||
}
|
||||
}
|
||||
|
||||
void frmComTool::on_ckAutoSave_stateChanged(int arg1)
|
||||
{
|
||||
if (arg1 == 0) {
|
||||
ui->cboxSaveInterval->setEnabled(false);
|
||||
timerSave->stop();
|
||||
} else {
|
||||
ui->cboxSaveInterval->setEnabled(true);
|
||||
timerSave->start();
|
||||
}
|
||||
}
|
||||
|
||||
void frmComTool::connectNet()
|
||||
{
|
||||
if (!tcpOk && App::AutoConnect && ui->btnStart->text() == "启动") {
|
||||
if (App::ServerIP != "" && App::ServerPort != 0) {
|
||||
socket->connectToHost(App::ServerIP, App::ServerPort);
|
||||
if (socket->waitForConnected(100)) {
|
||||
ui->btnStart->setText("停止");
|
||||
append(6, "连接服务器成功");
|
||||
tcpOk = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void frmComTool::readDataNet()
|
||||
{
|
||||
if (socket->bytesAvailable() > 0) {
|
||||
QUIHelper::sleep(App::SleepTime);
|
||||
QByteArray data = socket->readAll();
|
||||
|
||||
QString buffer;
|
||||
if (ui->ckHexReceive->isChecked()) {
|
||||
buffer = QUIHelper::byteArrayToHexStr(data);
|
||||
} else {
|
||||
buffer = QUIHelper::byteArrayToAsciiStr(data);
|
||||
}
|
||||
|
||||
append(5, buffer);
|
||||
|
||||
//将收到的网络数据转发给串口
|
||||
if (comOk) {
|
||||
com->write(data);
|
||||
append(0, buffer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void frmComTool::readErrorNet()
|
||||
{
|
||||
ui->btnStart->setText("启动");
|
||||
append(6, QString("连接服务器失败,%1").arg(socket->errorString()));
|
||||
socket->disconnectFromHost();
|
||||
tcpOk = false;
|
||||
}
|
|
@ -0,0 +1,68 @@
|
|||
#ifndef FRMCOMTOOL_H
|
||||
#define FRMCOMTOOL_H
|
||||
|
||||
#include <QWidget>
|
||||
#include "qtcpsocket.h"
|
||||
#include "qextserialport.h"
|
||||
|
||||
namespace Ui
|
||||
{
|
||||
class frmComTool;
|
||||
}
|
||||
|
||||
class frmComTool : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit frmComTool(QWidget *parent = 0);
|
||||
~frmComTool();
|
||||
|
||||
private:
|
||||
Ui::frmComTool *ui;
|
||||
|
||||
bool comOk; //串口是否打开
|
||||
QextSerialPort *com; //串口通信对象
|
||||
QTimer *timerRead; //定时读取串口数据
|
||||
QTimer *timerSend; //定时发送串口数据
|
||||
QTimer *timerSave; //定时保存串口数据
|
||||
|
||||
int sleepTime; //接收延时时间
|
||||
int sendCount; //发送数据计数
|
||||
int receiveCount; //接收数据计数
|
||||
bool isShow; //是否显示数据
|
||||
|
||||
bool tcpOk; //网络是否正常
|
||||
QTcpSocket *socket; //网络连接对象
|
||||
QTimer *timerConnect; //定时器重连
|
||||
|
||||
private slots:
|
||||
void initForm(); //初始化窗体数据
|
||||
void initConfig(); //初始化配置文件
|
||||
void saveConfig(); //保存配置文件
|
||||
void readData(); //读取串口数据
|
||||
void sendData(); //发送串口数据
|
||||
void sendData(QString data);//发送串口数据带参数
|
||||
void saveData(); //保存串口数据
|
||||
|
||||
void changeEnable(bool b); //改变状态
|
||||
void append(int type, const QString &data, bool clear = false);
|
||||
|
||||
private slots:
|
||||
void connectNet();
|
||||
void readDataNet();
|
||||
void readErrorNet();
|
||||
|
||||
private slots:
|
||||
void on_btnOpen_clicked();
|
||||
void on_btnStopShow_clicked();
|
||||
void on_btnSendCount_clicked();
|
||||
void on_btnReceiveCount_clicked();
|
||||
void on_btnClear_clicked();
|
||||
void on_btnData_clicked();
|
||||
void on_btnStart_clicked();
|
||||
void on_ckAutoSend_stateChanged(int arg1);
|
||||
void on_ckAutoSave_stateChanged(int arg1);
|
||||
};
|
||||
|
||||
#endif // FRMCOMTOOL_H
|
|
@ -0,0 +1,473 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>frmComTool</class>
|
||||
<widget class="QWidget" name="frmComTool">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>800</width>
|
||||
<height>600</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_6">
|
||||
<item row="0" column="0">
|
||||
<widget class="QTextEdit" name="txtMain">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::StyledPanel</enum>
|
||||
</property>
|
||||
<property name="verticalScrollBarPolicy">
|
||||
<enum>Qt::ScrollBarAsNeeded</enum>
|
||||
</property>
|
||||
<property name="horizontalScrollBarPolicy">
|
||||
<enum>Qt::ScrollBarAsNeeded</enum>
|
||||
</property>
|
||||
<property name="readOnly">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1" rowspan="2">
|
||||
<widget class="QWidget" name="widgetRight" native="true">
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>200</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QFrame" name="frameTop">
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::Box</enum>
|
||||
</property>
|
||||
<property name="frameShadow">
|
||||
<enum>QFrame::Sunken</enum>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_3">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="labPortName">
|
||||
<property name="text">
|
||||
<string>串口号</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QComboBox" name="cboxPortName">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||
<horstretch>1</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="labBaudRate">
|
||||
<property name="text">
|
||||
<string>波特率</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QComboBox" name="cboxBaudRate">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||
<horstretch>1</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="labDataBit">
|
||||
<property name="text">
|
||||
<string>数据位</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QComboBox" name="cboxDataBit">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||
<horstretch>1</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="labParity">
|
||||
<property name="text">
|
||||
<string>校验位</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QComboBox" name="cboxParity">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||
<horstretch>1</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<widget class="QLabel" name="labStopBit">
|
||||
<property name="text">
|
||||
<string>停止位</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1">
|
||||
<widget class="QComboBox" name="cboxStopBit">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||
<horstretch>1</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="0" colspan="2">
|
||||
<widget class="QPushButton" name="btnOpen">
|
||||
<property name="text">
|
||||
<string>打开串口</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QTabWidget" name="tabWidget">
|
||||
<property name="tabPosition">
|
||||
<enum>QTabWidget::South</enum>
|
||||
</property>
|
||||
<property name="currentIndex">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<widget class="QWidget" name="tab">
|
||||
<attribute name="title">
|
||||
<string>串口配置</string>
|
||||
</attribute>
|
||||
<layout class="QGridLayout" name="gridLayout_5">
|
||||
<item row="0" column="0">
|
||||
<widget class="QCheckBox" name="ckHexSend">
|
||||
<property name="text">
|
||||
<string>Hex发送</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QCheckBox" name="ckHexReceive">
|
||||
<property name="text">
|
||||
<string>Hex接收</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QCheckBox" name="ckDebug">
|
||||
<property name="text">
|
||||
<string>模拟设备</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QCheckBox" name="ckAutoClear">
|
||||
<property name="text">
|
||||
<string>自动清空</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0" colspan="2">
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="0" column="0">
|
||||
<widget class="QCheckBox" name="ckAutoSend">
|
||||
<property name="text">
|
||||
<string>自动发送</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QComboBox" name="cboxSendInterval">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QCheckBox" name="ckAutoSave">
|
||||
<property name="text">
|
||||
<string>自动保存</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QComboBox" name="cboxSaveInterval">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="3" column="0" colspan="2">
|
||||
<widget class="QPushButton" name="btnSendCount">
|
||||
<property name="text">
|
||||
<string>发送 : 0 字节</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0" colspan="2">
|
||||
<widget class="QPushButton" name="btnReceiveCount">
|
||||
<property name="text">
|
||||
<string>接收 : 0 字节</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="0" colspan="2">
|
||||
<widget class="QPushButton" name="btnStopShow">
|
||||
<property name="text">
|
||||
<string>停止显示</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="0" colspan="2">
|
||||
<widget class="QPushButton" name="btnSave">
|
||||
<property name="text">
|
||||
<string>保存数据</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="7" column="0" colspan="2">
|
||||
<widget class="QPushButton" name="btnData">
|
||||
<property name="text">
|
||||
<string>管理数据</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="8" column="0" colspan="2">
|
||||
<widget class="QPushButton" name="btnClear">
|
||||
<property name="text">
|
||||
<string>清空数据</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="9" column="0" colspan="2">
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>2</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="tab_2">
|
||||
<attribute name="title">
|
||||
<string>网络配置</string>
|
||||
</attribute>
|
||||
<layout class="QGridLayout" name="gridLayout_2">
|
||||
<item row="0" column="0" colspan="2">
|
||||
<layout class="QGridLayout" name="gridLayout_4">
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="labListenPort">
|
||||
<property name="text">
|
||||
<string>监听端口</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="labServerIP">
|
||||
<property name="text">
|
||||
<string>远程地址</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1">
|
||||
<widget class="QComboBox" name="cboxSleepTime"/>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QLineEdit" name="txtServerIP">
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="labServerPort">
|
||||
<property name="text">
|
||||
<string>远程端口</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QLineEdit" name="txtServerPort">
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<widget class="QLabel" name="labSleepTime">
|
||||
<property name="text">
|
||||
<string>延时时间</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QLineEdit" name="txtListenPort"/>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="labMode">
|
||||
<property name="text">
|
||||
<string>转换模式</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QComboBox" name="cboxMode">
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Tcp_Client</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Tcp_Server</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Udp_Client</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Udp_Server</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="2" column="0" colspan="2">
|
||||
<widget class="QPushButton" name="btnStart">
|
||||
<property name="text">
|
||||
<string>启动</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0" colspan="2">
|
||||
<spacer name="verticalSpacer_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>59</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="1" column="0" colspan="2">
|
||||
<widget class="QCheckBox" name="ckAutoConnect">
|
||||
<property name="text">
|
||||
<string>自动重连网络</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QWidget" name="widget" native="true">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QComboBox" name="cboxData">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Ignored" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="editable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="duplicatesEnabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="btnSend">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>80</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>80</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>发送</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
|
@ -0,0 +1,11 @@
|
|||
#include <QtCore>
|
||||
#include <QtGui>
|
||||
#include <QtNetwork>
|
||||
|
||||
#if (QT_VERSION > QT_VERSION_CHECK(5,0,0))
|
||||
#include <QtWidgets>
|
||||
#endif
|
||||
|
||||
#include "app.h"
|
||||
|
||||
#pragma execution_character_set("utf-8")
|
|
@ -0,0 +1,31 @@
|
|||
#include "frmcomtool.h"
|
||||
#include "quiwidget.h"
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
QApplication a(argc, argv);
|
||||
a.setWindowIcon(QIcon(":/main.ico"));
|
||||
|
||||
QFont font;
|
||||
font.setFamily(QUIConfig::FontName);
|
||||
font.setPixelSize(QUIConfig::FontSize);
|
||||
a.setFont(font);
|
||||
|
||||
//设置编码以及加载中文翻译文件
|
||||
QUIHelper::setCode();
|
||||
QUIHelper::setTranslator(":/qt_zh_CN.qm");
|
||||
QUIHelper::setTranslator(":/widgets.qm");
|
||||
QUIHelper::initRand();
|
||||
|
||||
App::Intervals << "1" << "10" << "20" << "50" << "100" << "200" << "300" << "500" << "1000" << "1500" << "2000" << "3000" << "5000" << "10000";
|
||||
App::ConfigFile = QString("%1/%2.ini").arg(QUIHelper::appPath()).arg(QUIHelper::appName());
|
||||
App::readConfig();
|
||||
App::readSendData();
|
||||
App::readDeviceData();
|
||||
|
||||
frmComTool w;
|
||||
w.setWindowTitle("串口调试助手V2019 QQ: 517216493");
|
||||
w.show();
|
||||
|
||||
return a.exec();
|
||||
}
|
Binary file not shown.
After Width: | Height: | Size: 91 KiB |
|
@ -0,0 +1,5 @@
|
|||
<RCC>
|
||||
<qresource prefix="/">
|
||||
<file>main.ico</file>
|
||||
</qresource>
|
||||
</RCC>
|
|
@ -0,0 +1 @@
|
|||
IDI_ICON1 ICON DISCARDABLE "main.ico"
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,234 @@
|
|||
/****************************************************************************
|
||||
** Copyright (c) 2000-2003 Wayne Roth
|
||||
** Copyright (c) 2004-2007 Stefan Sander
|
||||
** Copyright (c) 2007 Michal Policht
|
||||
** Copyright (c) 2008 Brandon Fosdick
|
||||
** Copyright (c) 2009-2010 Liam Staskawicz
|
||||
** Copyright (c) 2011 Debao Zhang
|
||||
** All right reserved.
|
||||
** Web: http://code.google.com/p/qextserialport/
|
||||
**
|
||||
** Permission is hereby granted, free of charge, to any person obtaining
|
||||
** a copy of this software and associated documentation files (the
|
||||
** "Software"), to deal in the Software without restriction, including
|
||||
** without limitation the rights to use, copy, modify, merge, publish,
|
||||
** distribute, sublicense, and/or sell copies of the Software, and to
|
||||
** permit persons to whom the Software is furnished to do so, subject to
|
||||
** the following conditions:
|
||||
**
|
||||
** The above copyright notice and this permission notice shall be
|
||||
** included in all copies or substantial portions of the Software.
|
||||
**
|
||||
** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
** LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
** OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
** WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef _QEXTSERIALPORT_H_
|
||||
#define _QEXTSERIALPORT_H_
|
||||
|
||||
#include <QtCore/QIODevice>
|
||||
#include "qextserialport_global.h"
|
||||
#ifdef Q_OS_UNIX
|
||||
#include <termios.h>
|
||||
#endif
|
||||
/*line status constants*/
|
||||
// ### QESP2.0 move to enum
|
||||
#define LS_CTS 0x01
|
||||
#define LS_DSR 0x02
|
||||
#define LS_DCD 0x04
|
||||
#define LS_RI 0x08
|
||||
#define LS_RTS 0x10
|
||||
#define LS_DTR 0x20
|
||||
#define LS_ST 0x40
|
||||
#define LS_SR 0x80
|
||||
|
||||
/*error constants*/
|
||||
// ### QESP2.0 move to enum
|
||||
#define E_NO_ERROR 0
|
||||
#define E_INVALID_FD 1
|
||||
#define E_NO_MEMORY 2
|
||||
#define E_CAUGHT_NON_BLOCKED_SIGNAL 3
|
||||
#define E_PORT_TIMEOUT 4
|
||||
#define E_INVALID_DEVICE 5
|
||||
#define E_BREAK_CONDITION 6
|
||||
#define E_FRAMING_ERROR 7
|
||||
#define E_IO_ERROR 8
|
||||
#define E_BUFFER_OVERRUN 9
|
||||
#define E_RECEIVE_OVERFLOW 10
|
||||
#define E_RECEIVE_PARITY_ERROR 11
|
||||
#define E_TRANSMIT_OVERFLOW 12
|
||||
#define E_READ_FAILED 13
|
||||
#define E_WRITE_FAILED 14
|
||||
#define E_FILE_NOT_FOUND 15
|
||||
#define E_PERMISSION_DENIED 16
|
||||
#define E_AGAIN 17
|
||||
|
||||
enum BaudRateType {
|
||||
#if defined(Q_OS_UNIX) || defined(qdoc)
|
||||
BAUD50 = 50, //POSIX ONLY
|
||||
BAUD75 = 75, //POSIX ONLY
|
||||
BAUD134 = 134, //POSIX ONLY
|
||||
BAUD150 = 150, //POSIX ONLY
|
||||
BAUD200 = 200, //POSIX ONLY
|
||||
BAUD1800 = 1800, //POSIX ONLY
|
||||
# if defined(B76800) || defined(qdoc)
|
||||
BAUD76800 = 76800, //POSIX ONLY
|
||||
# endif
|
||||
# if (defined(B230400) && defined(B4000000)) || defined(qdoc)
|
||||
BAUD230400 = 230400, //POSIX ONLY
|
||||
BAUD460800 = 460800, //POSIX ONLY
|
||||
BAUD500000 = 500000, //POSIX ONLY
|
||||
BAUD576000 = 576000, //POSIX ONLY
|
||||
BAUD921600 = 921600, //POSIX ONLY
|
||||
BAUD1000000 = 1000000, //POSIX ONLY
|
||||
BAUD1152000 = 1152000, //POSIX ONLY
|
||||
BAUD1500000 = 1500000, //POSIX ONLY
|
||||
BAUD2000000 = 2000000, //POSIX ONLY
|
||||
BAUD2500000 = 2500000, //POSIX ONLY
|
||||
BAUD3000000 = 3000000, //POSIX ONLY
|
||||
BAUD3500000 = 3500000, //POSIX ONLY
|
||||
BAUD4000000 = 4000000, //POSIX ONLY
|
||||
# endif
|
||||
#endif //Q_OS_UNIX
|
||||
#if defined(Q_OS_WIN) || defined(qdoc)
|
||||
BAUD14400 = 14400, //WINDOWS ONLY
|
||||
BAUD56000 = 56000, //WINDOWS ONLY
|
||||
BAUD128000 = 128000, //WINDOWS ONLY
|
||||
BAUD256000 = 256000, //WINDOWS ONLY
|
||||
#endif //Q_OS_WIN
|
||||
BAUD110 = 110,
|
||||
BAUD300 = 300,
|
||||
BAUD600 = 600,
|
||||
BAUD1200 = 1200,
|
||||
BAUD2400 = 2400,
|
||||
BAUD4800 = 4800,
|
||||
BAUD9600 = 9600,
|
||||
BAUD19200 = 19200,
|
||||
BAUD38400 = 38400,
|
||||
BAUD57600 = 57600,
|
||||
BAUD115200 = 115200
|
||||
};
|
||||
|
||||
enum DataBitsType {
|
||||
DATA_5 = 5,
|
||||
DATA_6 = 6,
|
||||
DATA_7 = 7,
|
||||
DATA_8 = 8
|
||||
};
|
||||
|
||||
enum ParityType {
|
||||
PAR_NONE,
|
||||
PAR_ODD,
|
||||
PAR_EVEN,
|
||||
#if defined(Q_OS_WIN) || defined(qdoc)
|
||||
PAR_MARK, //WINDOWS ONLY
|
||||
#endif
|
||||
PAR_SPACE
|
||||
};
|
||||
|
||||
enum StopBitsType {
|
||||
STOP_1,
|
||||
#if defined(Q_OS_WIN) || defined(qdoc)
|
||||
STOP_1_5, //WINDOWS ONLY
|
||||
#endif
|
||||
STOP_2
|
||||
};
|
||||
|
||||
enum FlowType {
|
||||
FLOW_OFF,
|
||||
FLOW_HARDWARE,
|
||||
FLOW_XONXOFF
|
||||
};
|
||||
|
||||
/**
|
||||
* structure to contain port settings
|
||||
*/
|
||||
struct PortSettings {
|
||||
BaudRateType BaudRate;
|
||||
DataBitsType DataBits;
|
||||
ParityType Parity;
|
||||
StopBitsType StopBits;
|
||||
FlowType FlowControl;
|
||||
long Timeout_Millisec;
|
||||
};
|
||||
|
||||
class QextSerialPortPrivate;
|
||||
class QEXTSERIALPORT_EXPORT QextSerialPort: public QIODevice
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_DECLARE_PRIVATE(QextSerialPort)
|
||||
Q_ENUMS(QueryMode)
|
||||
Q_PROPERTY(QString portName READ portName WRITE setPortName)
|
||||
Q_PROPERTY(QueryMode queryMode READ queryMode WRITE setQueryMode)
|
||||
public:
|
||||
enum QueryMode {
|
||||
Polling,
|
||||
EventDriven
|
||||
};
|
||||
|
||||
explicit QextSerialPort(QueryMode mode = EventDriven, QObject *parent = 0);
|
||||
explicit QextSerialPort(const QString &name, QueryMode mode = EventDriven, QObject *parent = 0);
|
||||
explicit QextSerialPort(const PortSettings &s, QueryMode mode = EventDriven, QObject *parent = 0);
|
||||
QextSerialPort(const QString &name, const PortSettings &s, QueryMode mode = EventDriven, QObject *parent = 0);
|
||||
|
||||
~QextSerialPort();
|
||||
|
||||
QString portName() const;
|
||||
QueryMode queryMode() const;
|
||||
BaudRateType baudRate() const;
|
||||
DataBitsType dataBits() const;
|
||||
ParityType parity() const;
|
||||
StopBitsType stopBits() const;
|
||||
FlowType flowControl() const;
|
||||
|
||||
bool open(OpenMode mode);
|
||||
bool isSequential() const;
|
||||
void close();
|
||||
void flush();
|
||||
qint64 bytesAvailable() const;
|
||||
bool canReadLine() const;
|
||||
QByteArray readAll();
|
||||
|
||||
ulong lastError() const;
|
||||
|
||||
ulong lineStatus();
|
||||
QString errorString();
|
||||
|
||||
public Q_SLOTS:
|
||||
void setPortName(const QString &name);
|
||||
void setQueryMode(QueryMode mode);
|
||||
void setBaudRate(BaudRateType);
|
||||
void setDataBits(DataBitsType);
|
||||
void setParity(ParityType);
|
||||
void setStopBits(StopBitsType);
|
||||
void setFlowControl(FlowType);
|
||||
void setTimeout(long);
|
||||
|
||||
void setDtr(bool set = true);
|
||||
void setRts(bool set = true);
|
||||
|
||||
Q_SIGNALS:
|
||||
void dsrChanged(bool status);
|
||||
|
||||
protected:
|
||||
qint64 readData(char *data, qint64 maxSize);
|
||||
qint64 writeData(const char *data, qint64 maxSize);
|
||||
|
||||
private:
|
||||
Q_DISABLE_COPY(QextSerialPort)
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
Q_PRIVATE_SLOT(d_func(), void _q_onWinEvent(HANDLE))
|
||||
#endif
|
||||
Q_PRIVATE_SLOT(d_func(), void _q_canRead())
|
||||
|
||||
QextSerialPortPrivate *const d_ptr;
|
||||
};
|
||||
|
||||
#endif
|
|
@ -0,0 +1,9 @@
|
|||
HEADERS += \
|
||||
$$PWD/qextserialport.h \
|
||||
$$PWD/qextserialport_global.h \
|
||||
$$PWD/qextserialport_p.h
|
||||
|
||||
SOURCES += $$PWD/qextserialport.cpp
|
||||
|
||||
win32:SOURCES += $$PWD/qextserialport_win.cpp
|
||||
unix:SOURCES += $$PWD/qextserialport_unix.cpp
|
|
@ -0,0 +1,72 @@
|
|||
/****************************************************************************
|
||||
** Copyright (c) 2000-2003 Wayne Roth
|
||||
** Copyright (c) 2004-2007 Stefan Sander
|
||||
** Copyright (c) 2007 Michal Policht
|
||||
** Copyright (c) 2008 Brandon Fosdick
|
||||
** Copyright (c) 2009-2010 Liam Staskawicz
|
||||
** Copyright (c) 2011 Debao Zhang
|
||||
** All right reserved.
|
||||
** Web: http://code.google.com/p/qextserialport/
|
||||
**
|
||||
** Permission is hereby granted, free of charge, to any person obtaining
|
||||
** a copy of this software and associated documentation files (the
|
||||
** "Software"), to deal in the Software without restriction, including
|
||||
** without limitation the rights to use, copy, modify, merge, publish,
|
||||
** distribute, sublicense, and/or sell copies of the Software, and to
|
||||
** permit persons to whom the Software is furnished to do so, subject to
|
||||
** the following conditions:
|
||||
**
|
||||
** The above copyright notice and this permission notice shall be
|
||||
** included in all copies or substantial portions of the Software.
|
||||
**
|
||||
** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
** LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
** OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
** WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef QEXTSERIALPORT_GLOBAL_H
|
||||
#define QEXTSERIALPORT_GLOBAL_H
|
||||
|
||||
#include <QtCore/QtGlobal>
|
||||
|
||||
#ifdef QEXTSERIALPORT_BUILD_SHARED
|
||||
# define QEXTSERIALPORT_EXPORT Q_DECL_EXPORT
|
||||
#elif defined(QEXTSERIALPORT_USING_SHARED)
|
||||
# define QEXTSERIALPORT_EXPORT Q_DECL_IMPORT
|
||||
#else
|
||||
# define QEXTSERIALPORT_EXPORT
|
||||
#endif
|
||||
|
||||
// ### for compatible with old version. should be removed in QESP 2.0
|
||||
#ifdef _TTY_NOWARN_
|
||||
# define QESP_NO_WARN
|
||||
#endif
|
||||
#ifdef _TTY_NOWARN_PORT_
|
||||
# define QESP_NO_PORTABILITY_WARN
|
||||
#endif
|
||||
|
||||
/*if all warning messages are turned off, flag portability warnings to be turned off as well*/
|
||||
#ifdef QESP_NO_WARN
|
||||
# define QESP_NO_PORTABILITY_WARN
|
||||
#endif
|
||||
|
||||
/*macros for warning and debug messages*/
|
||||
#ifdef QESP_NO_PORTABILITY_WARN
|
||||
# define QESP_PORTABILITY_WARNING while (false)qWarning
|
||||
#else
|
||||
# define QESP_PORTABILITY_WARNING qWarning
|
||||
#endif /*QESP_NOWARN_PORT*/
|
||||
|
||||
#ifdef QESP_NO_WARN
|
||||
# define QESP_WARNING while (false)qWarning
|
||||
#else
|
||||
# define QESP_WARNING qWarning
|
||||
#endif /*QESP_NOWARN*/
|
||||
|
||||
#endif // QEXTSERIALPORT_GLOBAL_H
|
||||
|
|
@ -0,0 +1,277 @@
|
|||
/****************************************************************************
|
||||
** Copyright (c) 2000-2003 Wayne Roth
|
||||
** Copyright (c) 2004-2007 Stefan Sander
|
||||
** Copyright (c) 2007 Michal Policht
|
||||
** Copyright (c) 2008 Brandon Fosdick
|
||||
** Copyright (c) 2009-2010 Liam Staskawicz
|
||||
** Copyright (c) 2011 Debao Zhang
|
||||
** All right reserved.
|
||||
** Web: http://code.google.com/p/qextserialport/
|
||||
**
|
||||
** Permission is hereby granted, free of charge, to any person obtaining
|
||||
** a copy of this software and associated documentation files (the
|
||||
** "Software"), to deal in the Software without restriction, including
|
||||
** without limitation the rights to use, copy, modify, merge, publish,
|
||||
** distribute, sublicense, and/or sell copies of the Software, and to
|
||||
** permit persons to whom the Software is furnished to do so, subject to
|
||||
** the following conditions:
|
||||
**
|
||||
** The above copyright notice and this permission notice shall be
|
||||
** included in all copies or substantial portions of the Software.
|
||||
**
|
||||
** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
** LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
** OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
** WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef _QEXTSERIALPORT_P_H_
|
||||
#define _QEXTSERIALPORT_P_H_
|
||||
|
||||
//
|
||||
// W A R N I N G
|
||||
// -------------
|
||||
//
|
||||
// This file is not part of the QESP API. It exists for the convenience
|
||||
// of other QESP classes. This header file may change from version to
|
||||
// version without notice, or even be removed.
|
||||
//
|
||||
// We mean it.
|
||||
//
|
||||
|
||||
#include "qextserialport.h"
|
||||
#include <QtCore/QReadWriteLock>
|
||||
#ifdef Q_OS_UNIX
|
||||
# include <termios.h>
|
||||
#elif (defined Q_OS_WIN)
|
||||
# include <QtCore/qt_windows.h>
|
||||
#endif
|
||||
#include <stdlib.h>
|
||||
|
||||
// This is QextSerialPort's read buffer, needed by posix system.
|
||||
// ref: QRingBuffer & QIODevicePrivateLinearBuffer
|
||||
class QextReadBuffer
|
||||
{
|
||||
public:
|
||||
inline QextReadBuffer(size_t growth = 4096)
|
||||
: len(0), first(0), buf(0), capacity(0), basicBlockSize(growth)
|
||||
{
|
||||
}
|
||||
|
||||
~QextReadBuffer()
|
||||
{
|
||||
delete buf;
|
||||
}
|
||||
|
||||
inline void clear()
|
||||
{
|
||||
first = buf;
|
||||
len = 0;
|
||||
}
|
||||
|
||||
inline int size() const
|
||||
{
|
||||
return len;
|
||||
}
|
||||
|
||||
inline bool isEmpty() const
|
||||
{
|
||||
return len == 0;
|
||||
}
|
||||
|
||||
inline int read(char *target, int size)
|
||||
{
|
||||
int r = qMin(size, len);
|
||||
|
||||
if (r == 1) {
|
||||
*target = *first;
|
||||
--len;
|
||||
++first;
|
||||
} else {
|
||||
memcpy(target, first, r);
|
||||
len -= r;
|
||||
first += r;
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
inline char *reserve(size_t size)
|
||||
{
|
||||
if ((first - buf) + len + size > capacity) {
|
||||
size_t newCapacity = qMax(capacity, basicBlockSize);
|
||||
|
||||
while (newCapacity < len + size) {
|
||||
newCapacity *= 2;
|
||||
}
|
||||
|
||||
if (newCapacity > capacity) {
|
||||
// allocate more space
|
||||
char *newBuf = new char[newCapacity];
|
||||
memmove(newBuf, first, len);
|
||||
delete buf;
|
||||
buf = newBuf;
|
||||
capacity = newCapacity;
|
||||
} else {
|
||||
// shift any existing data to make space
|
||||
memmove(buf, first, len);
|
||||
}
|
||||
|
||||
first = buf;
|
||||
}
|
||||
|
||||
char *writePtr = first + len;
|
||||
len += (int)size;
|
||||
return writePtr;
|
||||
}
|
||||
|
||||
inline void chop(int size)
|
||||
{
|
||||
if (size >= len) {
|
||||
clear();
|
||||
} else {
|
||||
len -= size;
|
||||
}
|
||||
}
|
||||
|
||||
inline void squeeze()
|
||||
{
|
||||
if (first != buf) {
|
||||
memmove(buf, first, len);
|
||||
first = buf;
|
||||
}
|
||||
|
||||
size_t newCapacity = basicBlockSize;
|
||||
|
||||
while (newCapacity < size_t(len)) {
|
||||
newCapacity *= 2;
|
||||
}
|
||||
|
||||
if (newCapacity < capacity) {
|
||||
char *tmp = static_cast<char *>(realloc(buf, newCapacity));
|
||||
|
||||
if (tmp) {
|
||||
buf = tmp;
|
||||
capacity = newCapacity;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
inline QByteArray readAll()
|
||||
{
|
||||
char *f = first;
|
||||
int l = len;
|
||||
clear();
|
||||
return QByteArray(f, l);
|
||||
}
|
||||
|
||||
inline int readLine(char *target, int size)
|
||||
{
|
||||
int r = qMin(size, len);
|
||||
char *eol = static_cast<char *>(memchr(first, '\n', r));
|
||||
|
||||
if (eol) {
|
||||
r = 1 + (eol - first);
|
||||
}
|
||||
|
||||
memcpy(target, first, r);
|
||||
len -= r;
|
||||
first += r;
|
||||
return int(r);
|
||||
}
|
||||
|
||||
inline bool canReadLine() const
|
||||
{
|
||||
return memchr(first, '\n', len);
|
||||
}
|
||||
|
||||
private:
|
||||
int len;
|
||||
char *first;
|
||||
char *buf;
|
||||
size_t capacity;
|
||||
size_t basicBlockSize;
|
||||
};
|
||||
|
||||
class QWinEventNotifier;
|
||||
class QReadWriteLock;
|
||||
class QSocketNotifier;
|
||||
|
||||
class QextSerialPortPrivate
|
||||
{
|
||||
Q_DECLARE_PUBLIC(QextSerialPort)
|
||||
public:
|
||||
QextSerialPortPrivate(QextSerialPort *q);
|
||||
~QextSerialPortPrivate();
|
||||
enum DirtyFlagEnum {
|
||||
DFE_BaudRate = 0x0001,
|
||||
DFE_Parity = 0x0002,
|
||||
DFE_StopBits = 0x0004,
|
||||
DFE_DataBits = 0x0008,
|
||||
DFE_Flow = 0x0010,
|
||||
DFE_TimeOut = 0x0100,
|
||||
DFE_ALL = 0x0fff,
|
||||
DFE_Settings_Mask = 0x00ff //without TimeOut
|
||||
};
|
||||
mutable QReadWriteLock lock;
|
||||
QString port;
|
||||
PortSettings settings;
|
||||
QextReadBuffer readBuffer;
|
||||
int settingsDirtyFlags;
|
||||
ulong lastErr;
|
||||
QextSerialPort::QueryMode queryMode;
|
||||
|
||||
// platform specific members
|
||||
#ifdef Q_OS_UNIX
|
||||
int fd;
|
||||
QSocketNotifier *readNotifier;
|
||||
struct termios currentTermios;
|
||||
struct termios oldTermios;
|
||||
#elif (defined Q_OS_WIN)
|
||||
HANDLE handle;
|
||||
OVERLAPPED overlap;
|
||||
COMMCONFIG commConfig;
|
||||
COMMTIMEOUTS commTimeouts;
|
||||
QWinEventNotifier *winEventNotifier;
|
||||
DWORD eventMask;
|
||||
QList<OVERLAPPED *> pendingWrites;
|
||||
QReadWriteLock *bytesToWriteLock;
|
||||
#endif
|
||||
|
||||
/*fill PortSettings*/
|
||||
void setBaudRate(BaudRateType baudRate, bool update = true);
|
||||
void setDataBits(DataBitsType dataBits, bool update = true);
|
||||
void setParity(ParityType parity, bool update = true);
|
||||
void setStopBits(StopBitsType stopbits, bool update = true);
|
||||
void setFlowControl(FlowType flow, bool update = true);
|
||||
void setTimeout(long millisec, bool update = true);
|
||||
void setPortSettings(const PortSettings &settings, bool update = true);
|
||||
|
||||
void platformSpecificDestruct();
|
||||
void platformSpecificInit();
|
||||
void translateError(ulong error);
|
||||
void updatePortSettings();
|
||||
|
||||
qint64 readData_sys(char *data, qint64 maxSize);
|
||||
qint64 writeData_sys(const char *data, qint64 maxSize);
|
||||
void setDtr_sys(bool set = true);
|
||||
void setRts_sys(bool set = true);
|
||||
bool open_sys(QIODevice::OpenMode mode);
|
||||
bool close_sys();
|
||||
bool flush_sys();
|
||||
ulong lineStatus_sys();
|
||||
qint64 bytesAvailable_sys() const;
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
void _q_onWinEvent(HANDLE h);
|
||||
#endif
|
||||
void _q_canRead();
|
||||
|
||||
QextSerialPort *q_ptr;
|
||||
};
|
||||
|
||||
#endif //_QEXTSERIALPORT_P_H_
|
|
@ -0,0 +1,559 @@
|
|||
/****************************************************************************
|
||||
** Copyright (c) 2000-2003 Wayne Roth
|
||||
** Copyright (c) 2004-2007 Stefan Sander
|
||||
** Copyright (c) 2007 Michal Policht
|
||||
** Copyright (c) 2008 Brandon Fosdick
|
||||
** Copyright (c) 2009-2010 Liam Staskawicz
|
||||
** Copyright (c) 2011 Debao Zhang
|
||||
** All right reserved.
|
||||
** Web: http://code.google.com/p/qextserialport/
|
||||
**
|
||||
** Permission is hereby granted, free of charge, to any person obtaining
|
||||
** a copy of this software and associated documentation files (the
|
||||
** "Software"), to deal in the Software without restriction, including
|
||||
** without limitation the rights to use, copy, modify, merge, publish,
|
||||
** distribute, sublicense, and/or sell copies of the Software, and to
|
||||
** permit persons to whom the Software is furnished to do so, subject to
|
||||
** the following conditions:
|
||||
**
|
||||
** The above copyright notice and this permission notice shall be
|
||||
** included in all copies or substantial portions of the Software.
|
||||
**
|
||||
** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
** LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
** OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
** WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include "qextserialport.h"
|
||||
#include "qextserialport_p.h"
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/select.h>
|
||||
#include <QtCore/QMutexLocker>
|
||||
#include <QtCore/QDebug>
|
||||
#include <QtCore/QSocketNotifier>
|
||||
|
||||
void QextSerialPortPrivate::platformSpecificInit()
|
||||
{
|
||||
fd = 0;
|
||||
readNotifier = 0;
|
||||
}
|
||||
|
||||
/*!
|
||||
Standard destructor.
|
||||
*/
|
||||
void QextSerialPortPrivate::platformSpecificDestruct()
|
||||
{
|
||||
}
|
||||
|
||||
static QString fullPortName(const QString &name)
|
||||
{
|
||||
if (name.startsWith(QLatin1Char('/'))) {
|
||||
return name;
|
||||
}
|
||||
|
||||
return QLatin1String("/dev/") + name;
|
||||
}
|
||||
|
||||
bool QextSerialPortPrivate::open_sys(QIODevice::OpenMode mode)
|
||||
{
|
||||
Q_Q(QextSerialPort);
|
||||
|
||||
//note: linux 2.6.21 seems to ignore O_NDELAY flag
|
||||
if ((fd = ::open(fullPortName(port).toLatin1() , O_RDWR | O_NOCTTY | O_NDELAY)) != -1) {
|
||||
|
||||
/*In the Private class, We can not call QIODevice::open()*/
|
||||
q->setOpenMode(mode); // Flag the port as opened
|
||||
::tcgetattr(fd, &oldTermios); // Save the old termios
|
||||
currentTermios = oldTermios; // Make a working copy
|
||||
::cfmakeraw(¤tTermios); // Enable raw access
|
||||
|
||||
/*set up other port settings*/
|
||||
currentTermios.c_cflag |= CREAD | CLOCAL;
|
||||
currentTermios.c_lflag &= (~(ICANON | ECHO | ECHOE | ECHOK | ECHONL | ISIG));
|
||||
currentTermios.c_iflag &= (~(INPCK | IGNPAR | PARMRK | ISTRIP | ICRNL | IXANY));
|
||||
currentTermios.c_oflag &= (~OPOST);
|
||||
currentTermios.c_cc[VMIN] = 0;
|
||||
#ifdef _POSIX_VDISABLE // Is a disable character available on this system?
|
||||
// Some systems allow for per-device disable-characters, so get the
|
||||
// proper value for the configured device
|
||||
const long vdisable = ::fpathconf(fd, _PC_VDISABLE);
|
||||
currentTermios.c_cc[VINTR] = vdisable;
|
||||
currentTermios.c_cc[VQUIT] = vdisable;
|
||||
currentTermios.c_cc[VSTART] = vdisable;
|
||||
currentTermios.c_cc[VSTOP] = vdisable;
|
||||
currentTermios.c_cc[VSUSP] = vdisable;
|
||||
#endif //_POSIX_VDISABLE
|
||||
settingsDirtyFlags = DFE_ALL;
|
||||
updatePortSettings();
|
||||
|
||||
if (queryMode == QextSerialPort::EventDriven) {
|
||||
readNotifier = new QSocketNotifier(fd, QSocketNotifier::Read, q);
|
||||
q->connect(readNotifier, SIGNAL(activated(int)), q, SLOT(_q_canRead()));
|
||||
}
|
||||
|
||||
return true;
|
||||
} else {
|
||||
translateError(errno);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool QextSerialPortPrivate::close_sys()
|
||||
{
|
||||
// Force a flush and then restore the original termios
|
||||
flush_sys();
|
||||
// Using both TCSAFLUSH and TCSANOW here discards any pending input
|
||||
::tcsetattr(fd, TCSAFLUSH | TCSANOW, &oldTermios); // Restore termios
|
||||
::close(fd);
|
||||
|
||||
if (readNotifier) {
|
||||
delete readNotifier;
|
||||
readNotifier = 0;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool QextSerialPortPrivate::flush_sys()
|
||||
{
|
||||
::tcdrain(fd);
|
||||
return true;
|
||||
}
|
||||
|
||||
qint64 QextSerialPortPrivate::bytesAvailable_sys() const
|
||||
{
|
||||
int bytesQueued;
|
||||
|
||||
if (::ioctl(fd, FIONREAD, &bytesQueued) == -1) {
|
||||
return (qint64) - 1;
|
||||
}
|
||||
|
||||
return bytesQueued;
|
||||
}
|
||||
|
||||
/*!
|
||||
Translates a system-specific error code to a QextSerialPort error code. Used internally.
|
||||
*/
|
||||
void QextSerialPortPrivate::translateError(ulong error)
|
||||
{
|
||||
switch (error) {
|
||||
case EBADF:
|
||||
case ENOTTY:
|
||||
lastErr = E_INVALID_FD;
|
||||
break;
|
||||
|
||||
case EINTR:
|
||||
lastErr = E_CAUGHT_NON_BLOCKED_SIGNAL;
|
||||
break;
|
||||
|
||||
case ENOMEM:
|
||||
lastErr = E_NO_MEMORY;
|
||||
break;
|
||||
|
||||
case EACCES:
|
||||
lastErr = E_PERMISSION_DENIED;
|
||||
break;
|
||||
|
||||
case EAGAIN:
|
||||
lastErr = E_AGAIN;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void QextSerialPortPrivate::setDtr_sys(bool set)
|
||||
{
|
||||
int status;
|
||||
::ioctl(fd, TIOCMGET, &status);
|
||||
|
||||
if (set) {
|
||||
status |= TIOCM_DTR;
|
||||
} else {
|
||||
status &= ~TIOCM_DTR;
|
||||
}
|
||||
|
||||
::ioctl(fd, TIOCMSET, &status);
|
||||
}
|
||||
|
||||
void QextSerialPortPrivate::setRts_sys(bool set)
|
||||
{
|
||||
int status;
|
||||
::ioctl(fd, TIOCMGET, &status);
|
||||
|
||||
if (set) {
|
||||
status |= TIOCM_RTS;
|
||||
} else {
|
||||
status &= ~TIOCM_RTS;
|
||||
}
|
||||
|
||||
::ioctl(fd, TIOCMSET, &status);
|
||||
}
|
||||
|
||||
unsigned long QextSerialPortPrivate::lineStatus_sys()
|
||||
{
|
||||
unsigned long Status = 0, Temp = 0;
|
||||
::ioctl(fd, TIOCMGET, &Temp);
|
||||
|
||||
if (Temp & TIOCM_CTS) {
|
||||
Status |= LS_CTS;
|
||||
}
|
||||
|
||||
if (Temp & TIOCM_DSR) {
|
||||
Status |= LS_DSR;
|
||||
}
|
||||
|
||||
if (Temp & TIOCM_RI) {
|
||||
Status |= LS_RI;
|
||||
}
|
||||
|
||||
if (Temp & TIOCM_CD) {
|
||||
Status |= LS_DCD;
|
||||
}
|
||||
|
||||
if (Temp & TIOCM_DTR) {
|
||||
Status |= LS_DTR;
|
||||
}
|
||||
|
||||
if (Temp & TIOCM_RTS) {
|
||||
Status |= LS_RTS;
|
||||
}
|
||||
|
||||
if (Temp & TIOCM_ST) {
|
||||
Status |= LS_ST;
|
||||
}
|
||||
|
||||
if (Temp & TIOCM_SR) {
|
||||
Status |= LS_SR;
|
||||
}
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
/*!
|
||||
Reads a block of data from the serial port. This function will read at most maxSize bytes from
|
||||
the serial port and place them in the buffer pointed to by data. Return value is the number of
|
||||
bytes actually read, or -1 on error.
|
||||
|
||||
\warning before calling this function ensure that serial port associated with this class
|
||||
is currently open (use isOpen() function to check if port is open).
|
||||
*/
|
||||
qint64 QextSerialPortPrivate::readData_sys(char *data, qint64 maxSize)
|
||||
{
|
||||
int retVal = ::read(fd, data, maxSize);
|
||||
|
||||
if (retVal == -1) {
|
||||
lastErr = E_READ_FAILED;
|
||||
}
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
/*!
|
||||
Writes a block of data to the serial port. This function will write maxSize bytes
|
||||
from the buffer pointed to by data to the serial port. Return value is the number
|
||||
of bytes actually written, or -1 on error.
|
||||
|
||||
\warning before calling this function ensure that serial port associated with this class
|
||||
is currently open (use isOpen() function to check if port is open).
|
||||
*/
|
||||
qint64 QextSerialPortPrivate::writeData_sys(const char *data, qint64 maxSize)
|
||||
{
|
||||
int retVal = ::write(fd, data, maxSize);
|
||||
|
||||
if (retVal == -1) {
|
||||
lastErr = E_WRITE_FAILED;
|
||||
}
|
||||
|
||||
return (qint64)retVal;
|
||||
}
|
||||
|
||||
static void setBaudRate2Termios(termios *config, int baudRate)
|
||||
{
|
||||
#ifdef CBAUD
|
||||
config->c_cflag &= (~CBAUD);
|
||||
config->c_cflag |= baudRate;
|
||||
#else
|
||||
::cfsetispeed(config, baudRate);
|
||||
::cfsetospeed(config, baudRate);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
All the platform settings was performed in this function.
|
||||
*/
|
||||
void QextSerialPortPrivate::updatePortSettings()
|
||||
{
|
||||
if (!q_func()->isOpen() || !settingsDirtyFlags) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (settingsDirtyFlags & DFE_BaudRate) {
|
||||
switch (settings.BaudRate) {
|
||||
case BAUD50:
|
||||
setBaudRate2Termios(¤tTermios, B50);
|
||||
break;
|
||||
|
||||
case BAUD75:
|
||||
setBaudRate2Termios(¤tTermios, B75);
|
||||
break;
|
||||
|
||||
case BAUD110:
|
||||
setBaudRate2Termios(¤tTermios, B110);
|
||||
break;
|
||||
|
||||
case BAUD134:
|
||||
setBaudRate2Termios(¤tTermios, B134);
|
||||
break;
|
||||
|
||||
case BAUD150:
|
||||
setBaudRate2Termios(¤tTermios, B150);
|
||||
break;
|
||||
|
||||
case BAUD200:
|
||||
setBaudRate2Termios(¤tTermios, B200);
|
||||
break;
|
||||
|
||||
case BAUD300:
|
||||
setBaudRate2Termios(¤tTermios, B300);
|
||||
break;
|
||||
|
||||
case BAUD600:
|
||||
setBaudRate2Termios(¤tTermios, B600);
|
||||
break;
|
||||
|
||||
case BAUD1200:
|
||||
setBaudRate2Termios(¤tTermios, B1200);
|
||||
break;
|
||||
|
||||
case BAUD1800:
|
||||
setBaudRate2Termios(¤tTermios, B1800);
|
||||
break;
|
||||
|
||||
case BAUD2400:
|
||||
setBaudRate2Termios(¤tTermios, B2400);
|
||||
break;
|
||||
|
||||
case BAUD4800:
|
||||
setBaudRate2Termios(¤tTermios, B4800);
|
||||
break;
|
||||
|
||||
case BAUD9600:
|
||||
setBaudRate2Termios(¤tTermios, B9600);
|
||||
break;
|
||||
|
||||
case BAUD19200:
|
||||
setBaudRate2Termios(¤tTermios, B19200);
|
||||
break;
|
||||
|
||||
case BAUD38400:
|
||||
setBaudRate2Termios(¤tTermios, B38400);
|
||||
break;
|
||||
|
||||
case BAUD57600:
|
||||
setBaudRate2Termios(¤tTermios, B57600);
|
||||
break;
|
||||
#ifdef B76800
|
||||
|
||||
case BAUD76800:
|
||||
setBaudRate2Termios(¤tTermios, B76800);
|
||||
break;
|
||||
#endif
|
||||
|
||||
case BAUD115200:
|
||||
setBaudRate2Termios(¤tTermios, B115200);
|
||||
break;
|
||||
#if defined(B230400) && defined(B4000000)
|
||||
|
||||
case BAUD230400:
|
||||
setBaudRate2Termios(¤tTermios, B230400);
|
||||
break;
|
||||
|
||||
case BAUD460800:
|
||||
setBaudRate2Termios(¤tTermios, B460800);
|
||||
break;
|
||||
|
||||
case BAUD500000:
|
||||
setBaudRate2Termios(¤tTermios, B500000);
|
||||
break;
|
||||
|
||||
case BAUD576000:
|
||||
setBaudRate2Termios(¤tTermios, B576000);
|
||||
break;
|
||||
|
||||
case BAUD921600:
|
||||
setBaudRate2Termios(¤tTermios, B921600);
|
||||
break;
|
||||
|
||||
case BAUD1000000:
|
||||
setBaudRate2Termios(¤tTermios, B1000000);
|
||||
break;
|
||||
|
||||
case BAUD1152000:
|
||||
setBaudRate2Termios(¤tTermios, B1152000);
|
||||
break;
|
||||
|
||||
case BAUD1500000:
|
||||
setBaudRate2Termios(¤tTermios, B1500000);
|
||||
break;
|
||||
|
||||
case BAUD2000000:
|
||||
setBaudRate2Termios(¤tTermios, B2000000);
|
||||
break;
|
||||
|
||||
case BAUD2500000:
|
||||
setBaudRate2Termios(¤tTermios, B2500000);
|
||||
break;
|
||||
|
||||
case BAUD3000000:
|
||||
setBaudRate2Termios(¤tTermios, B3000000);
|
||||
break;
|
||||
|
||||
case BAUD3500000:
|
||||
setBaudRate2Termios(¤tTermios, B3500000);
|
||||
break;
|
||||
|
||||
case BAUD4000000:
|
||||
setBaudRate2Termios(¤tTermios, B4000000);
|
||||
break;
|
||||
#endif
|
||||
#ifdef Q_OS_MAC
|
||||
|
||||
default:
|
||||
setBaudRate2Termios(¤tTermios, settings.BaudRate);
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
if (settingsDirtyFlags & DFE_Parity) {
|
||||
switch (settings.Parity) {
|
||||
case PAR_SPACE:
|
||||
/*space parity not directly supported - add an extra data bit to simulate it*/
|
||||
settingsDirtyFlags |= DFE_DataBits;
|
||||
break;
|
||||
|
||||
case PAR_NONE:
|
||||
currentTermios.c_cflag &= (~PARENB);
|
||||
break;
|
||||
|
||||
case PAR_EVEN:
|
||||
currentTermios.c_cflag &= (~PARODD);
|
||||
currentTermios.c_cflag |= PARENB;
|
||||
break;
|
||||
|
||||
case PAR_ODD:
|
||||
currentTermios.c_cflag |= (PARENB | PARODD);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*must after Parity settings*/
|
||||
if (settingsDirtyFlags & DFE_DataBits) {
|
||||
if (settings.Parity != PAR_SPACE) {
|
||||
currentTermios.c_cflag &= (~CSIZE);
|
||||
|
||||
switch (settings.DataBits) {
|
||||
case DATA_5:
|
||||
currentTermios.c_cflag |= CS5;
|
||||
break;
|
||||
|
||||
case DATA_6:
|
||||
currentTermios.c_cflag |= CS6;
|
||||
break;
|
||||
|
||||
case DATA_7:
|
||||
currentTermios.c_cflag |= CS7;
|
||||
break;
|
||||
|
||||
case DATA_8:
|
||||
currentTermios.c_cflag |= CS8;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
/*space parity not directly supported - add an extra data bit to simulate it*/
|
||||
currentTermios.c_cflag &= ~(PARENB | CSIZE);
|
||||
|
||||
switch (settings.DataBits) {
|
||||
case DATA_5:
|
||||
currentTermios.c_cflag |= CS6;
|
||||
break;
|
||||
|
||||
case DATA_6:
|
||||
currentTermios.c_cflag |= CS7;
|
||||
break;
|
||||
|
||||
case DATA_7:
|
||||
currentTermios.c_cflag |= CS8;
|
||||
break;
|
||||
|
||||
case DATA_8:
|
||||
/*this will never happen, put here to Suppress an warning*/
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (settingsDirtyFlags & DFE_StopBits) {
|
||||
switch (settings.StopBits) {
|
||||
case STOP_1:
|
||||
currentTermios.c_cflag &= (~CSTOPB);
|
||||
break;
|
||||
|
||||
case STOP_2:
|
||||
currentTermios.c_cflag |= CSTOPB;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (settingsDirtyFlags & DFE_Flow) {
|
||||
switch (settings.FlowControl) {
|
||||
case FLOW_OFF:
|
||||
currentTermios.c_cflag &= (~CRTSCTS);
|
||||
currentTermios.c_iflag &= (~(IXON | IXOFF | IXANY));
|
||||
break;
|
||||
|
||||
case FLOW_XONXOFF:
|
||||
/*software (XON/XOFF) flow control*/
|
||||
currentTermios.c_cflag &= (~CRTSCTS);
|
||||
currentTermios.c_iflag |= (IXON | IXOFF | IXANY);
|
||||
break;
|
||||
|
||||
case FLOW_HARDWARE:
|
||||
currentTermios.c_cflag |= CRTSCTS;
|
||||
currentTermios.c_iflag &= (~(IXON | IXOFF | IXANY));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*if any thing in currentTermios changed, flush*/
|
||||
if (settingsDirtyFlags & DFE_Settings_Mask) {
|
||||
::tcsetattr(fd, TCSAFLUSH, ¤tTermios);
|
||||
}
|
||||
|
||||
if (settingsDirtyFlags & DFE_TimeOut) {
|
||||
int millisec = settings.Timeout_Millisec;
|
||||
|
||||
if (millisec == -1) {
|
||||
::fcntl(fd, F_SETFL, O_NDELAY);
|
||||
} else {
|
||||
//O_SYNC should enable blocking ::write()
|
||||
//however this seems not working on Linux 2.6.21 (works on OpenBSD 4.2)
|
||||
::fcntl(fd, F_SETFL, O_SYNC);
|
||||
}
|
||||
|
||||
::tcgetattr(fd, ¤tTermios);
|
||||
currentTermios.c_cc[VTIME] = millisec / 100;
|
||||
::tcsetattr(fd, TCSAFLUSH, ¤tTermios);
|
||||
}
|
||||
|
||||
settingsDirtyFlags = 0;
|
||||
}
|
|
@ -0,0 +1,476 @@
|
|||
/****************************************************************************
|
||||
** Copyright (c) 2000-2003 Wayne Roth
|
||||
** Copyright (c) 2004-2007 Stefan Sander
|
||||
** Copyright (c) 2007 Michal Policht
|
||||
** Copyright (c) 2008 Brandon Fosdick
|
||||
** Copyright (c) 2009-2010 Liam Staskawicz
|
||||
** Copyright (c) 2011 Debao Zhang
|
||||
** All right reserved.
|
||||
** Web: http://code.google.com/p/qextserialport/
|
||||
**
|
||||
** Permission is hereby granted, free of charge, to any person obtaining
|
||||
** a copy of this software and associated documentation files (the
|
||||
** "Software"), to deal in the Software without restriction, including
|
||||
** without limitation the rights to use, copy, modify, merge, publish,
|
||||
** distribute, sublicense, and/or sell copies of the Software, and to
|
||||
** permit persons to whom the Software is furnished to do so, subject to
|
||||
** the following conditions:
|
||||
**
|
||||
** The above copyright notice and this permission notice shall be
|
||||
** included in all copies or substantial portions of the Software.
|
||||
**
|
||||
** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
** LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
** OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
** WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include "qextserialport.h"
|
||||
#include "qextserialport_p.h"
|
||||
#include <QtCore/QThread>
|
||||
#include <QtCore/QReadWriteLock>
|
||||
#include <QtCore/QMutexLocker>
|
||||
#include <QtCore/QDebug>
|
||||
#include <QtCore/QRegExp>
|
||||
#include <QtCore/QMetaType>
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0)
|
||||
# include <QtCore/QWinEventNotifier>
|
||||
#else
|
||||
# include <QtCore/private/qwineventnotifier_p.h>
|
||||
#endif
|
||||
void QextSerialPortPrivate::platformSpecificInit()
|
||||
{
|
||||
handle = INVALID_HANDLE_VALUE;
|
||||
ZeroMemory(&overlap, sizeof(OVERLAPPED));
|
||||
overlap.hEvent = CreateEvent(NULL, true, false, NULL);
|
||||
winEventNotifier = 0;
|
||||
bytesToWriteLock = new QReadWriteLock;
|
||||
}
|
||||
|
||||
void QextSerialPortPrivate::platformSpecificDestruct()
|
||||
{
|
||||
CloseHandle(overlap.hEvent);
|
||||
delete bytesToWriteLock;
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
\internal
|
||||
COM ports greater than 9 need \\.\ prepended
|
||||
|
||||
This is only need when open the port.
|
||||
*/
|
||||
static QString fullPortNameWin(const QString &name)
|
||||
{
|
||||
QRegExp rx(QLatin1String("^COM(\\d+)"));
|
||||
QString fullName(name);
|
||||
|
||||
if (fullName.contains(rx)) {
|
||||
fullName.prepend(QLatin1String("\\\\.\\"));
|
||||
}
|
||||
|
||||
return fullName;
|
||||
}
|
||||
|
||||
bool QextSerialPortPrivate::open_sys(QIODevice::OpenMode mode)
|
||||
{
|
||||
Q_Q(QextSerialPort);
|
||||
DWORD confSize = sizeof(COMMCONFIG);
|
||||
commConfig.dwSize = confSize;
|
||||
DWORD dwFlagsAndAttributes = 0;
|
||||
|
||||
if (queryMode == QextSerialPort::EventDriven) {
|
||||
dwFlagsAndAttributes += FILE_FLAG_OVERLAPPED;
|
||||
}
|
||||
|
||||
/*open the port*/
|
||||
handle = CreateFileW((wchar_t *)fullPortNameWin(port).utf16(), GENERIC_READ | GENERIC_WRITE,
|
||||
0, NULL, OPEN_EXISTING, dwFlagsAndAttributes, NULL);
|
||||
|
||||
if (handle != INVALID_HANDLE_VALUE) {
|
||||
q->setOpenMode(mode);
|
||||
/*configure port settings*/
|
||||
GetCommConfig(handle, &commConfig, &confSize);
|
||||
GetCommState(handle, &(commConfig.dcb));
|
||||
|
||||
/*set up parameters*/
|
||||
commConfig.dcb.fBinary = TRUE;
|
||||
commConfig.dcb.fInX = FALSE;
|
||||
commConfig.dcb.fOutX = FALSE;
|
||||
commConfig.dcb.fAbortOnError = FALSE;
|
||||
commConfig.dcb.fNull = FALSE;
|
||||
/* Dtr default to true. See Issue 122*/
|
||||
commConfig.dcb.fDtrControl = TRUE;
|
||||
/*flush all settings*/
|
||||
settingsDirtyFlags = DFE_ALL;
|
||||
updatePortSettings();
|
||||
|
||||
//init event driven approach
|
||||
if (queryMode == QextSerialPort::EventDriven) {
|
||||
if (!SetCommMask(handle, EV_TXEMPTY | EV_RXCHAR | EV_DSR)) {
|
||||
QESP_WARNING() << "failed to set Comm Mask. Error code:" << GetLastError();
|
||||
return false;
|
||||
}
|
||||
|
||||
winEventNotifier = new QWinEventNotifier(overlap.hEvent, q);
|
||||
qRegisterMetaType<HANDLE>("HANDLE");
|
||||
q->connect(winEventNotifier, SIGNAL(activated(HANDLE)), q, SLOT(_q_onWinEvent(HANDLE)), Qt::DirectConnection);
|
||||
WaitCommEvent(handle, &eventMask, &overlap);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool QextSerialPortPrivate::close_sys()
|
||||
{
|
||||
flush_sys();
|
||||
CancelIo(handle);
|
||||
|
||||
if (CloseHandle(handle)) {
|
||||
handle = INVALID_HANDLE_VALUE;
|
||||
}
|
||||
|
||||
if (winEventNotifier) {
|
||||
winEventNotifier->setEnabled(false);
|
||||
winEventNotifier->deleteLater();
|
||||
winEventNotifier = 0;
|
||||
}
|
||||
|
||||
foreach (OVERLAPPED *o, pendingWrites) {
|
||||
CloseHandle(o->hEvent);
|
||||
delete o;
|
||||
}
|
||||
|
||||
pendingWrites.clear();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool QextSerialPortPrivate::flush_sys()
|
||||
{
|
||||
FlushFileBuffers(handle);
|
||||
return true;
|
||||
}
|
||||
|
||||
qint64 QextSerialPortPrivate::bytesAvailable_sys() const
|
||||
{
|
||||
DWORD Errors;
|
||||
COMSTAT Status;
|
||||
|
||||
if (ClearCommError(handle, &Errors, &Status)) {
|
||||
return Status.cbInQue;
|
||||
}
|
||||
|
||||
return (qint64) - 1;
|
||||
}
|
||||
|
||||
/*
|
||||
Translates a system-specific error code to a QextSerialPort error code. Used internally.
|
||||
*/
|
||||
void QextSerialPortPrivate::translateError(ulong error)
|
||||
{
|
||||
if (error & CE_BREAK) {
|
||||
lastErr = E_BREAK_CONDITION;
|
||||
} else if (error & CE_FRAME) {
|
||||
lastErr = E_FRAMING_ERROR;
|
||||
} else if (error & CE_IOE) {
|
||||
lastErr = E_IO_ERROR;
|
||||
} else if (error & CE_MODE) {
|
||||
lastErr = E_INVALID_FD;
|
||||
} else if (error & CE_OVERRUN) {
|
||||
lastErr = E_BUFFER_OVERRUN;
|
||||
} else if (error & CE_RXPARITY) {
|
||||
lastErr = E_RECEIVE_PARITY_ERROR;
|
||||
} else if (error & CE_RXOVER) {
|
||||
lastErr = E_RECEIVE_OVERFLOW;
|
||||
} else if (error & CE_TXFULL) {
|
||||
lastErr = E_TRANSMIT_OVERFLOW;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Reads a block of data from the serial port. This function will read at most maxlen bytes from
|
||||
the serial port and place them in the buffer pointed to by data. Return value is the number of
|
||||
bytes actually read, or -1 on error.
|
||||
|
||||
\warning before calling this function ensure that serial port associated with this class
|
||||
is currently open (use isOpen() function to check if port is open).
|
||||
*/
|
||||
qint64 QextSerialPortPrivate::readData_sys(char *data, qint64 maxSize)
|
||||
{
|
||||
DWORD bytesRead = 0;
|
||||
bool failed = false;
|
||||
|
||||
if (queryMode == QextSerialPort::EventDriven) {
|
||||
OVERLAPPED overlapRead;
|
||||
ZeroMemory(&overlapRead, sizeof(OVERLAPPED));
|
||||
|
||||
if (!ReadFile(handle, (void *)data, (DWORD)maxSize, &bytesRead, &overlapRead)) {
|
||||
if (GetLastError() == ERROR_IO_PENDING) {
|
||||
GetOverlappedResult(handle, &overlapRead, &bytesRead, true);
|
||||
} else {
|
||||
failed = true;
|
||||
}
|
||||
}
|
||||
} else if (!ReadFile(handle, (void *)data, (DWORD)maxSize, &bytesRead, NULL)) {
|
||||
failed = true;
|
||||
}
|
||||
|
||||
if (!failed) {
|
||||
return (qint64)bytesRead;
|
||||
}
|
||||
|
||||
lastErr = E_READ_FAILED;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
Writes a block of data to the serial port. This function will write len bytes
|
||||
from the buffer pointed to by data to the serial port. Return value is the number
|
||||
of bytes actually written, or -1 on error.
|
||||
|
||||
\warning before calling this function ensure that serial port associated with this class
|
||||
is currently open (use isOpen() function to check if port is open).
|
||||
*/
|
||||
qint64 QextSerialPortPrivate::writeData_sys(const char *data, qint64 maxSize)
|
||||
{
|
||||
DWORD bytesWritten = 0;
|
||||
bool failed = false;
|
||||
|
||||
if (queryMode == QextSerialPort::EventDriven) {
|
||||
OVERLAPPED *newOverlapWrite = new OVERLAPPED;
|
||||
ZeroMemory(newOverlapWrite, sizeof(OVERLAPPED));
|
||||
newOverlapWrite->hEvent = CreateEvent(NULL, true, false, NULL);
|
||||
|
||||
if (WriteFile(handle, (void *)data, (DWORD)maxSize, &bytesWritten, newOverlapWrite)) {
|
||||
CloseHandle(newOverlapWrite->hEvent);
|
||||
delete newOverlapWrite;
|
||||
} else if (GetLastError() == ERROR_IO_PENDING) {
|
||||
// writing asynchronously...not an error
|
||||
QWriteLocker writelocker(bytesToWriteLock);
|
||||
pendingWrites.append(newOverlapWrite);
|
||||
} else {
|
||||
QESP_WARNING() << "QextSerialPort write error:" << GetLastError();
|
||||
failed = true;
|
||||
|
||||
if (!CancelIo(newOverlapWrite->hEvent)) {
|
||||
QESP_WARNING("QextSerialPort: couldn't cancel IO");
|
||||
}
|
||||
|
||||
if (!CloseHandle(newOverlapWrite->hEvent)) {
|
||||
QESP_WARNING("QextSerialPort: couldn't close OVERLAPPED handle");
|
||||
}
|
||||
|
||||
delete newOverlapWrite;
|
||||
}
|
||||
} else if (!WriteFile(handle, (void *)data, (DWORD)maxSize, &bytesWritten, NULL)) {
|
||||
failed = true;
|
||||
}
|
||||
|
||||
if (!failed) {
|
||||
return (qint64)bytesWritten;
|
||||
}
|
||||
|
||||
lastErr = E_WRITE_FAILED;
|
||||
return -1;
|
||||
}
|
||||
|
||||
void QextSerialPortPrivate::setDtr_sys(bool set)
|
||||
{
|
||||
EscapeCommFunction(handle, set ? SETDTR : CLRDTR);
|
||||
}
|
||||
|
||||
void QextSerialPortPrivate::setRts_sys(bool set)
|
||||
{
|
||||
EscapeCommFunction(handle, set ? SETRTS : CLRRTS);
|
||||
}
|
||||
|
||||
ulong QextSerialPortPrivate::lineStatus_sys(void)
|
||||
{
|
||||
unsigned long Status = 0, Temp = 0;
|
||||
GetCommModemStatus(handle, &Temp);
|
||||
|
||||
if (Temp & MS_CTS_ON) {
|
||||
Status |= LS_CTS;
|
||||
}
|
||||
|
||||
if (Temp & MS_DSR_ON) {
|
||||
Status |= LS_DSR;
|
||||
}
|
||||
|
||||
if (Temp & MS_RING_ON) {
|
||||
Status |= LS_RI;
|
||||
}
|
||||
|
||||
if (Temp & MS_RLSD_ON) {
|
||||
Status |= LS_DCD;
|
||||
}
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
/*
|
||||
Triggered when there's activity on our HANDLE.
|
||||
*/
|
||||
void QextSerialPortPrivate::_q_onWinEvent(HANDLE h)
|
||||
{
|
||||
Q_Q(QextSerialPort);
|
||||
|
||||
if (h == overlap.hEvent) {
|
||||
if (eventMask & EV_RXCHAR) {
|
||||
if (q->sender() != q && bytesAvailable_sys() > 0) {
|
||||
_q_canRead();
|
||||
}
|
||||
}
|
||||
|
||||
if (eventMask & EV_TXEMPTY) {
|
||||
/*
|
||||
A write completed. Run through the list of OVERLAPPED writes, and if
|
||||
they completed successfully, take them off the list and delete them.
|
||||
Otherwise, leave them on there so they can finish.
|
||||
*/
|
||||
qint64 totalBytesWritten = 0;
|
||||
QList<OVERLAPPED *> overlapsToDelete;
|
||||
|
||||
foreach (OVERLAPPED *o, pendingWrites) {
|
||||
DWORD numBytes = 0;
|
||||
|
||||
if (GetOverlappedResult(handle, o, &numBytes, false)) {
|
||||
overlapsToDelete.append(o);
|
||||
totalBytesWritten += numBytes;
|
||||
} else if (GetLastError() != ERROR_IO_INCOMPLETE) {
|
||||
overlapsToDelete.append(o);
|
||||
QESP_WARNING() << "CommEvent overlapped write error:" << GetLastError();
|
||||
}
|
||||
}
|
||||
|
||||
if (q->sender() != q && totalBytesWritten > 0) {
|
||||
QWriteLocker writelocker(bytesToWriteLock);
|
||||
Q_EMIT q->bytesWritten(totalBytesWritten);
|
||||
}
|
||||
|
||||
foreach (OVERLAPPED *o, overlapsToDelete) {
|
||||
OVERLAPPED *toDelete = pendingWrites.takeAt(pendingWrites.indexOf(o));
|
||||
CloseHandle(toDelete->hEvent);
|
||||
delete toDelete;
|
||||
}
|
||||
}
|
||||
|
||||
if (eventMask & EV_DSR) {
|
||||
if (lineStatus_sys() & LS_DSR) {
|
||||
Q_EMIT q->dsrChanged(true);
|
||||
} else {
|
||||
Q_EMIT q->dsrChanged(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
WaitCommEvent(handle, &eventMask, &overlap);
|
||||
}
|
||||
|
||||
void QextSerialPortPrivate::updatePortSettings()
|
||||
{
|
||||
if (!q_ptr->isOpen() || !settingsDirtyFlags) {
|
||||
return;
|
||||
}
|
||||
|
||||
//fill struct : COMMCONFIG
|
||||
if (settingsDirtyFlags & DFE_BaudRate) {
|
||||
commConfig.dcb.BaudRate = settings.BaudRate;
|
||||
}
|
||||
|
||||
if (settingsDirtyFlags & DFE_Parity) {
|
||||
commConfig.dcb.Parity = (BYTE)settings.Parity;
|
||||
commConfig.dcb.fParity = (settings.Parity == PAR_NONE) ? FALSE : TRUE;
|
||||
}
|
||||
|
||||
if (settingsDirtyFlags & DFE_DataBits) {
|
||||
commConfig.dcb.ByteSize = (BYTE)settings.DataBits;
|
||||
}
|
||||
|
||||
if (settingsDirtyFlags & DFE_StopBits) {
|
||||
switch (settings.StopBits) {
|
||||
case STOP_1:
|
||||
commConfig.dcb.StopBits = ONESTOPBIT;
|
||||
break;
|
||||
|
||||
case STOP_1_5:
|
||||
commConfig.dcb.StopBits = ONE5STOPBITS;
|
||||
break;
|
||||
|
||||
case STOP_2:
|
||||
commConfig.dcb.StopBits = TWOSTOPBITS;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (settingsDirtyFlags & DFE_Flow) {
|
||||
switch (settings.FlowControl) {
|
||||
/*no flow control*/
|
||||
case FLOW_OFF:
|
||||
commConfig.dcb.fOutxCtsFlow = FALSE;
|
||||
commConfig.dcb.fRtsControl = RTS_CONTROL_DISABLE;
|
||||
commConfig.dcb.fInX = FALSE;
|
||||
commConfig.dcb.fOutX = FALSE;
|
||||
break;
|
||||
|
||||
/*software (XON/XOFF) flow control*/
|
||||
case FLOW_XONXOFF:
|
||||
commConfig.dcb.fOutxCtsFlow = FALSE;
|
||||
commConfig.dcb.fRtsControl = RTS_CONTROL_DISABLE;
|
||||
commConfig.dcb.fInX = TRUE;
|
||||
commConfig.dcb.fOutX = TRUE;
|
||||
break;
|
||||
|
||||
/*hardware flow control*/
|
||||
case FLOW_HARDWARE:
|
||||
commConfig.dcb.fOutxCtsFlow = TRUE;
|
||||
commConfig.dcb.fRtsControl = RTS_CONTROL_HANDSHAKE;
|
||||
commConfig.dcb.fInX = FALSE;
|
||||
commConfig.dcb.fOutX = FALSE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//fill struct : COMMTIMEOUTS
|
||||
if (settingsDirtyFlags & DFE_TimeOut) {
|
||||
if (queryMode != QextSerialPort::EventDriven) {
|
||||
int millisec = settings.Timeout_Millisec;
|
||||
|
||||
if (millisec == -1) {
|
||||
commTimeouts.ReadIntervalTimeout = MAXDWORD;
|
||||
commTimeouts.ReadTotalTimeoutConstant = 0;
|
||||
} else {
|
||||
commTimeouts.ReadIntervalTimeout = millisec;
|
||||
commTimeouts.ReadTotalTimeoutConstant = millisec;
|
||||
}
|
||||
|
||||
commTimeouts.ReadTotalTimeoutMultiplier = 0;
|
||||
commTimeouts.WriteTotalTimeoutMultiplier = millisec;
|
||||
commTimeouts.WriteTotalTimeoutConstant = 0;
|
||||
} else {
|
||||
commTimeouts.ReadIntervalTimeout = MAXDWORD;
|
||||
commTimeouts.ReadTotalTimeoutMultiplier = 0;
|
||||
commTimeouts.ReadTotalTimeoutConstant = 0;
|
||||
commTimeouts.WriteTotalTimeoutMultiplier = 0;
|
||||
commTimeouts.WriteTotalTimeoutConstant = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (settingsDirtyFlags & DFE_Settings_Mask) {
|
||||
SetCommConfig(handle, &commConfig, sizeof(COMMCONFIG));
|
||||
}
|
||||
|
||||
if ((settingsDirtyFlags & DFE_TimeOut)) {
|
||||
SetCommTimeouts(handle, &commTimeouts);
|
||||
}
|
||||
|
||||
settingsDirtyFlags = 0;
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
使用方法:
|
||||
pro文件
|
||||
include(qextserialport/qextserialport.pri)
|
||||
|
||||
QextSerialPort *GSM_COM = new QextSerialPort(portName, QextSerialPort::EventDriven);
|
||||
isOpen = GSM_COM->open(QIODevice::ReadWrite);
|
||||
if (isOpen) {
|
||||
GSM_COM->flush();
|
||||
GSM_COM->setBaudRate(BAUD9600);
|
||||
GSM_COM->setDataBits(DATA_8);
|
||||
GSM_COM->setParity(PAR_NONE);
|
||||
GSM_COM->setStopBits(STOP_1);
|
||||
GSM_COM->setFlowControl(FLOW_OFF);
|
||||
GSM_COM->setTimeout(10);
|
||||
}
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
基本功能:
|
||||
1:支持16进制数据发送与接收。
|
||||
2:支持windows下COM9以上的串口通信。
|
||||
3:实时显示收发数据字节大小以及串口状态。
|
||||
4:支持任意qt版本,亲测4.7.0 4.8.5 4.8.7 5.4.1 5.7.0 5.8.0。
|
||||
5:支持串口转网络数据收发。
|
||||
|
||||
高级功能:
|
||||
1:可自由管理需要发送的数据,每次只要从下拉框中选择数据即可,无需重新输入数据。
|
||||
2:可模拟设备回复数据,需要在主界面开启模拟设备回复数据。当接收到设置好的指令时,立即回复设置的回复指令。例如指定收到0x16 0x00 0xFF 0x01需要回复0x16 0x00 0xFE 0x01,则只需要在SendData.txt中添加一条数据16 00 FF 01:16 00 FE 01即可。
|
||||
3:可定时发送数据和保存数据到文本文件:,默认间隔5秒钟,可更改间隔时间。
|
||||
4:在不断接收到大量数据时,可以暂停显示数据来查看具体数据,后台依然接收数据但不处理,无需关闭串口来查看已接收到的数据。
|
||||
5:每次收到的数据都是完整的一条数据,而不是脱节的,做了延时处理。
|
||||
6:一套源码随处编译,无需更改串口通信类,已在XP/WIN7/UBUNTU/ARMLINUX系统下成功编译并运行。
|
||||
|
||||
如果有更好的建议或者意见,请Q我(517216493),谢谢!
|
Loading…
Reference in New Issue