新增串口调试助手

master
feiyangqingyun 2019-09-29 11:06:55 +08:00
parent 82155f24fc
commit 46ec08b3fd
26 changed files with 8807 additions and 0 deletions

7
comtool/api/api.pri Normal file
View File

@ -0,0 +1,7 @@
HEADERS += \
$$PWD/app.h \
$$PWD/quiwidget.h
SOURCES += \
$$PWD/app.cpp \
$$PWD/quiwidget.cpp

201
comtool/api/app.cpp Normal file
View File

@ -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();
}
}

51
comtool/api/app.h Normal file
View File

@ -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

3688
comtool/api/quiwidget.cpp Normal file

File diff suppressed because it is too large Load Diff

871
comtool/api/quiwidget.h Normal file
View File

@ -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

36
comtool/comtool.pro Normal file
View File

@ -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

1
comtool/file/device.txt Normal file
View File

@ -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

17
comtool/file/send.txt Normal file
View File

@ -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

8
comtool/form/form.pri Normal file
View File

@ -0,0 +1,8 @@
FORMS += \
$$PWD/frmcomtool.ui
HEADERS += \
$$PWD/frmcomtool.h
SOURCES += \
$$PWD/frmcomtool.cpp

584
comtool/form/frmcomtool.cpp Normal file
View File

@ -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;
}

68
comtool/form/frmcomtool.h Normal file
View File

@ -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

473
comtool/form/frmcomtool.ui Normal file
View File

@ -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>

11
comtool/head.h Normal file
View File

@ -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")

31
comtool/main.cpp Normal file
View File

@ -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();
}

BIN
comtool/other/main.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 91 KiB

5
comtool/other/main.qrc Normal file
View File

@ -0,0 +1,5 @@
<RCC>
<qresource prefix="/">
<file>main.ico</file>
</qresource>
</RCC>

1
comtool/other/main.rc Normal file
View File

@ -0,0 +1 @@
IDI_ICON1 ICON DISCARDABLE "main.ico"

File diff suppressed because it is too large Load Diff

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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_

View File

@ -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(&currentTermios); // 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(&currentTermios, B50);
break;
case BAUD75:
setBaudRate2Termios(&currentTermios, B75);
break;
case BAUD110:
setBaudRate2Termios(&currentTermios, B110);
break;
case BAUD134:
setBaudRate2Termios(&currentTermios, B134);
break;
case BAUD150:
setBaudRate2Termios(&currentTermios, B150);
break;
case BAUD200:
setBaudRate2Termios(&currentTermios, B200);
break;
case BAUD300:
setBaudRate2Termios(&currentTermios, B300);
break;
case BAUD600:
setBaudRate2Termios(&currentTermios, B600);
break;
case BAUD1200:
setBaudRate2Termios(&currentTermios, B1200);
break;
case BAUD1800:
setBaudRate2Termios(&currentTermios, B1800);
break;
case BAUD2400:
setBaudRate2Termios(&currentTermios, B2400);
break;
case BAUD4800:
setBaudRate2Termios(&currentTermios, B4800);
break;
case BAUD9600:
setBaudRate2Termios(&currentTermios, B9600);
break;
case BAUD19200:
setBaudRate2Termios(&currentTermios, B19200);
break;
case BAUD38400:
setBaudRate2Termios(&currentTermios, B38400);
break;
case BAUD57600:
setBaudRate2Termios(&currentTermios, B57600);
break;
#ifdef B76800
case BAUD76800:
setBaudRate2Termios(&currentTermios, B76800);
break;
#endif
case BAUD115200:
setBaudRate2Termios(&currentTermios, B115200);
break;
#if defined(B230400) && defined(B4000000)
case BAUD230400:
setBaudRate2Termios(&currentTermios, B230400);
break;
case BAUD460800:
setBaudRate2Termios(&currentTermios, B460800);
break;
case BAUD500000:
setBaudRate2Termios(&currentTermios, B500000);
break;
case BAUD576000:
setBaudRate2Termios(&currentTermios, B576000);
break;
case BAUD921600:
setBaudRate2Termios(&currentTermios, B921600);
break;
case BAUD1000000:
setBaudRate2Termios(&currentTermios, B1000000);
break;
case BAUD1152000:
setBaudRate2Termios(&currentTermios, B1152000);
break;
case BAUD1500000:
setBaudRate2Termios(&currentTermios, B1500000);
break;
case BAUD2000000:
setBaudRate2Termios(&currentTermios, B2000000);
break;
case BAUD2500000:
setBaudRate2Termios(&currentTermios, B2500000);
break;
case BAUD3000000:
setBaudRate2Termios(&currentTermios, B3000000);
break;
case BAUD3500000:
setBaudRate2Termios(&currentTermios, B3500000);
break;
case BAUD4000000:
setBaudRate2Termios(&currentTermios, B4000000);
break;
#endif
#ifdef Q_OS_MAC
default:
setBaudRate2Termios(&currentTermios, 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, &currentTermios);
}
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, &currentTermios);
currentTermios.c_cc[VTIME] = millisec / 100;
::tcsetattr(fd, TCSAFLUSH, &currentTermios);
}
settingsDirtyFlags = 0;
}

View File

@ -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;
}

View File

@ -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);
}

16
comtool/readme.txt Normal file
View File

@ -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),谢谢!