mirror of
https://github.com/x-tools-author/x-tools.git
synced 2025-09-15 15:28:40 +08:00
chore: remove useless files
This commit is contained in:
parent
fa498769cf
commit
b33cfa1b39
@ -1,15 +0,0 @@
|
||||
/***************************************************************************************************
|
||||
* Copyright 2023-2024 x-tools-author(x-tools@outlook.com). All rights reserved.
|
||||
*
|
||||
* The file is encoded using "utf8 with bom", it is a part of xTools project.
|
||||
*
|
||||
* xTools is licensed according to the terms in the file LICENCE(GPL V3) in the root of the source
|
||||
* code directory.
|
||||
**************************************************************************************************/
|
||||
#include "xToolsCanBusStudio.h"
|
||||
|
||||
xToolsCanBusStudio::xToolsCanBusStudio(QObject* parent)
|
||||
: QThread(parent)
|
||||
{}
|
||||
|
||||
xToolsCanBusStudio::~xToolsCanBusStudio() {}
|
||||
@ -1,19 +0,0 @@
|
||||
/***************************************************************************************************
|
||||
* Copyright 2023-2024 x-tools-author(x-tools@outlook.com). All rights reserved.
|
||||
*
|
||||
* The file is encoded using "utf8 with bom", it is a part of xTools project.
|
||||
*
|
||||
* xTools is licensed according to the terms in the file LICENCE(GPL V3) in the root of the source
|
||||
* code directory.
|
||||
**************************************************************************************************/
|
||||
#pragma once
|
||||
|
||||
#include <QThread>
|
||||
|
||||
class xToolsCanBusStudio : public QThread
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
xToolsCanBusStudio(QObject *parent = nullptr);
|
||||
~xToolsCanBusStudio();
|
||||
};
|
||||
@ -1,550 +0,0 @@
|
||||
/***************************************************************************************************
|
||||
* Copyright 2023-2024 x-tools-author(x-tools@outlook.com). All rights reserved.
|
||||
*
|
||||
* The file is encoded using "utf8 with bom", it is a part of xTools project.
|
||||
*
|
||||
* xTools is licensed according to the terms in the file LICENCE(GPL V3) in the root of the source
|
||||
* code directory.
|
||||
**************************************************************************************************/
|
||||
#include "xToolsCanBusStudioUi.h"
|
||||
#include "ui_xToolsCanBusStudioUi.h"
|
||||
|
||||
#include <QCanBus>
|
||||
#include <QCheckBox>
|
||||
#include <QDateTime>
|
||||
#include <QLineEdit>
|
||||
#include <QLoggingCategory>
|
||||
#include <QMessageBox>
|
||||
#include <QVector>
|
||||
|
||||
#include "xToolsSettings.h"
|
||||
|
||||
const QLoggingCategory gLC("sak.canstudio");
|
||||
|
||||
xToolsCanBusStudioUi::xToolsCanBusStudioUi(QWidget* parent)
|
||||
: QWidget{parent}
|
||||
, ui(new Ui::xToolsCanBusStudioUi)
|
||||
, mDevice(Q_NULLPTR)
|
||||
{
|
||||
if (!mSettings) {
|
||||
mSettings = xToolsSettings::instance();
|
||||
}
|
||||
|
||||
ui->setupUi(this);
|
||||
initUi();
|
||||
initSetting();
|
||||
|
||||
// Device is not connected.
|
||||
updateUiState(false);
|
||||
}
|
||||
|
||||
xToolsCanBusStudioUi::~xToolsCanBusStudioUi()
|
||||
{
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void xToolsCanBusStudioUi::initUi()
|
||||
{
|
||||
initUiSelectPlugin();
|
||||
initUiSpecifyConfiguration();
|
||||
initUiCanFrame();
|
||||
initUiSendCanFrame();
|
||||
}
|
||||
|
||||
void xToolsCanBusStudioUi::initUiSelectPlugin()
|
||||
{
|
||||
ui->pluginComboBox->clear();
|
||||
ui->pluginComboBox->addItems(QCanBus::instance()->plugins());
|
||||
ui->disconnectPushButton->setEnabled(false);
|
||||
ui->connectPushButton->setEnabled(true);
|
||||
|
||||
connect(ui->pluginComboBox,
|
||||
static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged),
|
||||
this,
|
||||
&xToolsCanBusStudioUi::onPluginChanged);
|
||||
connect(ui->disconnectPushButton,
|
||||
&QPushButton::clicked,
|
||||
this,
|
||||
&xToolsCanBusStudioUi::onDisconnectClicked);
|
||||
connect(ui->connectPushButton, &QPushButton::clicked, this, &xToolsCanBusStudioUi::onConnectClicked);
|
||||
}
|
||||
|
||||
void xToolsCanBusStudioUi::initUiSpecifyConfiguration()
|
||||
{
|
||||
setOptions(ui->loopbackComboBox, true);
|
||||
setOptions(ui->receivOwnComboBox, true);
|
||||
setOptions(ui->canFdComboBox, false);
|
||||
setBitRates(ui->bitrateComboBox, false);
|
||||
setBitRates(ui->dataBitrateComboBox, true);
|
||||
|
||||
ui->interfaceNameComboBox->lineEdit()->setPlaceholderText(tr("can0"));
|
||||
|
||||
connect(ui->customConfigurationCheckBox,
|
||||
&QCheckBox::clicked,
|
||||
this,
|
||||
&xToolsCanBusStudioUi::onCustomConfigurationChanged);
|
||||
connect(ui->loopbackComboBox,
|
||||
static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged),
|
||||
this,
|
||||
&xToolsCanBusStudioUi::onLoopbackIndexChanged);
|
||||
connect(ui->receivOwnComboBox,
|
||||
static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged),
|
||||
this,
|
||||
&xToolsCanBusStudioUi::onReceiveOwnIndexChanged);
|
||||
connect(ui->canFdComboBox,
|
||||
static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged),
|
||||
this,
|
||||
&xToolsCanBusStudioUi::onCanFdIndexChanged);
|
||||
connect(ui->bitrateComboBox,
|
||||
static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged),
|
||||
this,
|
||||
&xToolsCanBusStudioUi::onBitrateChanged);
|
||||
connect(ui->dataBitrateComboBox,
|
||||
static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged),
|
||||
this,
|
||||
&xToolsCanBusStudioUi::onDataBitrateChanged);
|
||||
connect(ui->customBitrateCheckBox,
|
||||
&QCheckBox::clicked,
|
||||
this,
|
||||
&xToolsCanBusStudioUi::onCustomBitrateChanged);
|
||||
connect(ui->customDataBitrateCheckBox,
|
||||
&QCheckBox::clicked,
|
||||
this,
|
||||
&xToolsCanBusStudioUi::onCustomDataBitrateChanged);
|
||||
}
|
||||
|
||||
void xToolsCanBusStudioUi::initUiCanFrame()
|
||||
{
|
||||
ui->frameTypeComboBox->clear();
|
||||
ui->frameTypeComboBox->addItem(tr("DataFrame"), QCanBusFrame::DataFrame);
|
||||
ui->frameTypeComboBox->addItem(tr("ErrorFrame"), QCanBusFrame::ErrorFrame);
|
||||
ui->frameTypeComboBox->addItem(tr("RemoteRequestFrame"), QCanBusFrame::RemoteRequestFrame);
|
||||
|
||||
connect(ui->frameTypeComboBox,
|
||||
static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged),
|
||||
this,
|
||||
&xToolsCanBusStudioUi::onFrameTypeChanged);
|
||||
connect(ui->extendedFormatCheckBox,
|
||||
&QCheckBox::clicked,
|
||||
this,
|
||||
&xToolsCanBusStudioUi::onExtendedFormatChanged);
|
||||
connect(ui->flexibleDataRateCheckBox,
|
||||
&QCheckBox::clicked,
|
||||
this,
|
||||
&xToolsCanBusStudioUi::onFlexibleDataRateChanged);
|
||||
connect(ui->bitrateSwitchCheckBox,
|
||||
&QCheckBox::clicked,
|
||||
this,
|
||||
&xToolsCanBusStudioUi::onBitrateSwitchChanged);
|
||||
}
|
||||
|
||||
void xToolsCanBusStudioUi::initUiSendCanFrame()
|
||||
{
|
||||
const QString inputTips = tr("Hex");
|
||||
ui->frameIdComboBox->lineEdit()->setPlaceholderText(inputTips);
|
||||
ui->payloadComboBox->lineEdit()->setPlaceholderText(inputTips);
|
||||
|
||||
connect(ui->sendPushButton, &QPushButton::clicked, this, &xToolsCanBusStudioUi::onSendButtonClicked);
|
||||
}
|
||||
|
||||
void xToolsCanBusStudioUi::initSetting()
|
||||
{
|
||||
initSettingSelectPlugin();
|
||||
initSettingSpecifyConfiguration();
|
||||
initSettingCanFrame();
|
||||
initSettingSendCanFrame();
|
||||
}
|
||||
|
||||
void xToolsCanBusStudioUi::initSettingSelectPlugin()
|
||||
{
|
||||
setCurrentIndex(ui->pluginComboBox, mSettingKeyCtx.pluginIndex);
|
||||
}
|
||||
|
||||
void xToolsCanBusStudioUi::initSettingSpecifyConfiguration()
|
||||
{
|
||||
QString name = mSettings->value(mSettingKeyCtx.interfaceName).toString();
|
||||
ui->interfaceNameComboBox->lineEdit()->setText(name);
|
||||
|
||||
setChecked(ui->customConfigurationCheckBox, mSettingKeyCtx.customConfiguration);
|
||||
setCurrentIndex(ui->loopbackComboBox, mSettingKeyCtx.loopback);
|
||||
setCurrentIndex(ui->receivOwnComboBox, mSettingKeyCtx.receiveOwn);
|
||||
setCurrentIndex(ui->bitrateComboBox, mSettingKeyCtx.bitrate);
|
||||
setCurrentIndex(ui->canFdComboBox, mSettingKeyCtx.canFd);
|
||||
setCurrentIndex(ui->dataBitrateComboBox, mSettingKeyCtx.dataBitRate);
|
||||
setChecked(ui->customBitrateCheckBox, mSettingKeyCtx.customBitRate);
|
||||
setChecked(ui->customDataBitrateCheckBox, mSettingKeyCtx.customDataBitRate);
|
||||
|
||||
bool enable = mSettings->value(mSettingKeyCtx.customConfiguration).toBool();
|
||||
setCustomConfigurationEnable(enable);
|
||||
}
|
||||
|
||||
void xToolsCanBusStudioUi::initSettingCanFrame()
|
||||
{
|
||||
setCurrentIndex(ui->frameTypeComboBox, mSettingKeyCtx.frameTypeIndex);
|
||||
setChecked(ui->extendedFormatCheckBox, mSettingKeyCtx.extendedFormat);
|
||||
setChecked(ui->flexibleDataRateCheckBox, mSettingKeyCtx.flexibleDataRate);
|
||||
setChecked(ui->bitrateSwitchCheckBox, mSettingKeyCtx.bitrateSwitch);
|
||||
|
||||
onFrameTypeChanged();
|
||||
}
|
||||
|
||||
void xToolsCanBusStudioUi::initSettingSendCanFrame() {}
|
||||
|
||||
void xToolsCanBusStudioUi::onPluginChanged()
|
||||
{
|
||||
int index = ui->pluginComboBox->currentIndex();
|
||||
mSettings->setValue(mSettingKeyCtx.pluginIndex, index);
|
||||
}
|
||||
|
||||
void xToolsCanBusStudioUi::onDisconnectClicked()
|
||||
{
|
||||
if (mDevice) {
|
||||
mDevice->disconnectDevice();
|
||||
mDevice->deleteLater();
|
||||
mDevice = Q_NULLPTR;
|
||||
}
|
||||
|
||||
updateUiState(false);
|
||||
}
|
||||
|
||||
void xToolsCanBusStudioUi::onConnectClicked()
|
||||
{
|
||||
const QString pluginName = ui->pluginComboBox->currentText();
|
||||
const QString interfaceName = ui->interfaceNameComboBox->currentText();
|
||||
|
||||
if (interfaceName.isEmpty()) {
|
||||
QMessageBox::warning(this,
|
||||
tr("Interface Name is Empty"),
|
||||
tr("Interface name is empty, "
|
||||
"please input the name then try again!"));
|
||||
return;
|
||||
}
|
||||
|
||||
QString errorString;
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(5, 9, 0)
|
||||
mDevice = QCanBus::instance()->createDevice(pluginName, interfaceName, &errorString);
|
||||
if (!mDevice) {
|
||||
qCWarning(gLC) << errorString;
|
||||
return;
|
||||
}
|
||||
#else
|
||||
mDevice = QCanBus::instance()->createDevice(pluginName.toLatin1(), interfaceName);
|
||||
if (!mDevice) {
|
||||
qCWarning(gLC) << tr("Create device failed!");
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
connect(mDevice, &QCanBusDevice::errorOccurred, this, &xToolsCanBusStudioUi::onErrorOccure);
|
||||
connect(mDevice, &QCanBusDevice::framesReceived, this, &xToolsCanBusStudioUi::onFrameReceived);
|
||||
connect(mDevice, &QCanBusDevice::framesWritten, this, &xToolsCanBusStudioUi::onFrameWritten);
|
||||
|
||||
auto items = configurationItems();
|
||||
for (auto& item : items) {
|
||||
mDevice->setConfigurationParameter(item.first, item.second);
|
||||
}
|
||||
|
||||
if (!mDevice->connectDevice()) {
|
||||
qCWarning(gLC) << tr("Connection error: %1").arg(mDevice->errorString());
|
||||
QMessageBox::warning(this,
|
||||
tr("Connection Error"),
|
||||
tr("Connection error: %1").arg(mDevice->errorString()));
|
||||
mDevice->deleteLater();
|
||||
mDevice = Q_NULLPTR;
|
||||
return;
|
||||
}
|
||||
|
||||
mSettings->setValue(mSettingKeyCtx.interfaceName, interfaceName);
|
||||
updateUiState(true);
|
||||
}
|
||||
|
||||
void xToolsCanBusStudioUi::onLoopbackIndexChanged(int index)
|
||||
{
|
||||
mSettings->setValue(mSettingKeyCtx.loopback, index);
|
||||
}
|
||||
|
||||
void xToolsCanBusStudioUi::onCustomConfigurationChanged()
|
||||
{
|
||||
bool checked = ui->customConfigurationCheckBox->isChecked();
|
||||
setCustomConfigurationEnable(checked);
|
||||
mSettings->setValue(mSettingKeyCtx.customConfiguration, checked);
|
||||
}
|
||||
|
||||
void xToolsCanBusStudioUi::onReceiveOwnIndexChanged(int index)
|
||||
{
|
||||
mSettings->setValue(mSettingKeyCtx.receiveOwn, index);
|
||||
}
|
||||
|
||||
void xToolsCanBusStudioUi::onCanFdIndexChanged(int index)
|
||||
{
|
||||
mSettings->setValue(mSettingKeyCtx.canFd, index);
|
||||
}
|
||||
|
||||
void xToolsCanBusStudioUi::onBitrateChanged(int index)
|
||||
{
|
||||
mSettings->setValue(mSettingKeyCtx.bitrate, index);
|
||||
}
|
||||
|
||||
void xToolsCanBusStudioUi::onDataBitrateChanged(int index)
|
||||
{
|
||||
mSettings->setValue(mSettingKeyCtx.dataBitRate, index);
|
||||
}
|
||||
|
||||
void xToolsCanBusStudioUi::onCustomBitrateChanged()
|
||||
{
|
||||
bool checked = ui->customBitrateCheckBox->isChecked();
|
||||
mSettings->setValue(mSettingKeyCtx.customBitRate, checked);
|
||||
|
||||
ui->bitrateComboBox->setEditable(checked);
|
||||
}
|
||||
|
||||
void xToolsCanBusStudioUi::onCustomDataBitrateChanged()
|
||||
{
|
||||
bool checked = ui->customDataBitrateCheckBox->isChecked();
|
||||
mSettings->setValue(mSettingKeyCtx.customDataBitRate, checked);
|
||||
|
||||
ui->dataBitrateComboBox->setEditable(true);
|
||||
}
|
||||
|
||||
void xToolsCanBusStudioUi::onFrameTypeChanged()
|
||||
{
|
||||
int index = ui->frameTypeComboBox->currentIndex();
|
||||
mSettings->setValue(mSettingKeyCtx.frameTypeIndex, index);
|
||||
|
||||
int type = ui->frameTypeComboBox->currentData().toInt();
|
||||
if (type == QCanBusFrame::DataFrame) {
|
||||
ui->flexibleDataRateCheckBox->setEnabled(true);
|
||||
bool checked = ui->flexibleDataRateCheckBox->isChecked();
|
||||
ui->bitrateSwitchCheckBox->setEnabled(checked);
|
||||
} else {
|
||||
ui->flexibleDataRateCheckBox->setEnabled(false);
|
||||
ui->bitrateSwitchCheckBox->setEnabled(false);
|
||||
}
|
||||
}
|
||||
|
||||
void xToolsCanBusStudioUi::onExtendedFormatChanged()
|
||||
{
|
||||
bool checked = ui->extendedFormatCheckBox->isChecked();
|
||||
mSettings->setValue(mSettingKeyCtx.extendedFormat, checked);
|
||||
}
|
||||
|
||||
void xToolsCanBusStudioUi::onFlexibleDataRateChanged()
|
||||
{
|
||||
bool checked = ui->flexibleDataRateCheckBox->isChecked();
|
||||
mSettings->setValue(mSettingKeyCtx.flexibleDataRate, checked);
|
||||
|
||||
ui->bitrateSwitchCheckBox->setEnabled(checked);
|
||||
}
|
||||
|
||||
void xToolsCanBusStudioUi::onBitrateSwitchChanged()
|
||||
{
|
||||
bool checked = ui->bitrateSwitchCheckBox->isChecked();
|
||||
mSettings->setValue(mSettingKeyCtx.bitrateSwitch, checked);
|
||||
}
|
||||
|
||||
void xToolsCanBusStudioUi::onSendButtonClicked()
|
||||
{
|
||||
if (!mDevice) {
|
||||
QString title = tr("Device is Not Ready");
|
||||
QString msg = tr("Device is not ready,"
|
||||
" please connect the device then try angin!");
|
||||
QMessageBox::warning(this, title, msg);
|
||||
return;
|
||||
}
|
||||
|
||||
const uint frameId = ui->frameIdComboBox->currentText().toUInt(Q_NULLPTR, 16);
|
||||
QString data = ui->payloadComboBox->currentText().trimmed();
|
||||
const QByteArray payload = QByteArray::fromHex(data.remove(QLatin1Char(' ')).toLatin1());
|
||||
|
||||
QCanBusFrame frame = QCanBusFrame(frameId, payload);
|
||||
frame.setExtendedFrameFormat(ui->extendedFormatCheckBox->isChecked());
|
||||
|
||||
if (ui->flexibleDataRateCheckBox->isEnabled()) {
|
||||
frame.setFlexibleDataRateFormat(ui->flexibleDataRateCheckBox->isChecked());
|
||||
}
|
||||
|
||||
if (ui->bitrateSwitchCheckBox->isEnabled()) {
|
||||
frame.setBitrateSwitch(ui->bitrateSwitchCheckBox);
|
||||
}
|
||||
|
||||
if (mDevice->writeFrame(frame)) {
|
||||
QString view;
|
||||
if (frame.frameType() == QCanBusFrame::ErrorFrame) {
|
||||
view = mDevice->interpretErrorFrame(frame);
|
||||
} else {
|
||||
view = frame.toString();
|
||||
}
|
||||
|
||||
QString flag = QString("<font color=green>[Tx] </font>");
|
||||
outputMessage(flag + view);
|
||||
} else {
|
||||
qCWarning(gLC) << mDevice->errorString();
|
||||
}
|
||||
}
|
||||
|
||||
void xToolsCanBusStudioUi::onErrorOccure(QCanBusDevice::CanBusError error)
|
||||
{
|
||||
if (mDevice) {
|
||||
Q_UNUSED(error);
|
||||
QMessageBox::warning(this, tr("Error Occure"), mDevice->errorString());
|
||||
onDisconnectClicked();
|
||||
}
|
||||
}
|
||||
|
||||
void xToolsCanBusStudioUi::onFrameReceived()
|
||||
{
|
||||
if (!mDevice) {
|
||||
return;
|
||||
}
|
||||
|
||||
while (mDevice->framesAvailable()) {
|
||||
const QCanBusFrame frame = mDevice->readFrame();
|
||||
|
||||
QString view;
|
||||
if (frame.frameType() == QCanBusFrame::ErrorFrame) {
|
||||
view = mDevice->interpretErrorFrame(frame);
|
||||
} else {
|
||||
view = frame.toString();
|
||||
}
|
||||
|
||||
QString flag = QString("<font color=blue>[Rx] </font>");
|
||||
outputMessage(flag + view);
|
||||
}
|
||||
}
|
||||
|
||||
void xToolsCanBusStudioUi::onFrameWritten(qint64 framesCount)
|
||||
{
|
||||
qCInfo(gLC) << framesCount;
|
||||
}
|
||||
|
||||
void xToolsCanBusStudioUi::setOptions(QComboBox* cb, bool usingUnspecified)
|
||||
{
|
||||
if (cb) {
|
||||
cb->clear();
|
||||
if (usingUnspecified) {
|
||||
cb->addItem(tr("unspecified"), QVariant());
|
||||
}
|
||||
cb->addItem(tr("false"), QVariant(false));
|
||||
cb->addItem(tr("true"), QVariant(true));
|
||||
}
|
||||
}
|
||||
|
||||
void xToolsCanBusStudioUi::setCurrentIndex(QComboBox* cb, const QString& key)
|
||||
{
|
||||
int index = mSettings->value(key).toInt();
|
||||
if (index >= 0 && index <= cb->count() - 1) {
|
||||
cb->setCurrentIndex(index);
|
||||
}
|
||||
}
|
||||
|
||||
void xToolsCanBusStudioUi::setChecked(QCheckBox* cb, const QString& key)
|
||||
{
|
||||
if (cb) {
|
||||
bool checked = mSettings->value(key).toBool();
|
||||
cb->setChecked(checked);
|
||||
}
|
||||
}
|
||||
|
||||
void xToolsCanBusStudioUi::setCustomConfigurationEnable(bool enable)
|
||||
{
|
||||
ui->errorFilterComboBox->setEnabled(enable);
|
||||
ui->loopbackComboBox->setEnabled(enable);
|
||||
ui->receivOwnComboBox->setEnabled(enable);
|
||||
ui->canFdComboBox->setEnabled(enable);
|
||||
ui->bitrateComboBox->setEnabled(enable);
|
||||
ui->dataBitrateComboBox->setEnabled(enable);
|
||||
ui->customBitrateCheckBox->setEnabled(enable);
|
||||
ui->customDataBitrateCheckBox->setEnabled(enable);
|
||||
}
|
||||
|
||||
void xToolsCanBusStudioUi::outputMessage(const QString& msg)
|
||||
{
|
||||
QString datetimeString =
|
||||
#if 0
|
||||
QDateTime::currentDateTime().toString("yyyy/MM/dd hh:mm:ss.zzz");
|
||||
#else
|
||||
QDateTime::currentDateTime().toString("hh:mm:ss.zzz");
|
||||
#endif
|
||||
QString cookedMsg;
|
||||
cookedMsg = QString("<font color=silver>%1 </font>").arg(datetimeString);
|
||||
cookedMsg += msg;
|
||||
|
||||
ui->textBrowser->append(cookedMsg);
|
||||
}
|
||||
|
||||
void xToolsCanBusStudioUi::updateUiState(bool connected)
|
||||
{
|
||||
ui->connectPushButton->setEnabled(!connected);
|
||||
ui->disconnectPushButton->setEnabled(connected);
|
||||
|
||||
ui->interfaceNameComboBox->setEnabled(!connected);
|
||||
ui->customConfigurationCheckBox->setEnabled(!connected);
|
||||
if (connected) {
|
||||
setCustomConfigurationEnable(false);
|
||||
} else {
|
||||
bool checked = ui->customConfigurationCheckBox->isChecked();
|
||||
setCustomConfigurationEnable(checked);
|
||||
}
|
||||
}
|
||||
|
||||
QVector<xToolsCanBusStudioUi::ConfigurationItem> xToolsCanBusStudioUi::configurationItems()
|
||||
{
|
||||
QVector<xToolsCanBusStudioUi::ConfigurationItem> items;
|
||||
ConfigurationItem item;
|
||||
|
||||
QString errorFilter = ui->errorFilterComboBox->currentText();
|
||||
if (!errorFilter.isEmpty()) {
|
||||
bool ok = false;
|
||||
int dec = errorFilter.toInt(&ok);
|
||||
if (ok) {
|
||||
item.first = QCanBusDevice::ErrorFilterKey;
|
||||
item.second = QVariant::fromValue(QCanBusFrame::FrameErrors(dec));
|
||||
items.append(item);
|
||||
}
|
||||
}
|
||||
|
||||
item.first = QCanBusDevice::LoopbackKey;
|
||||
item.second = ui->loopbackComboBox->currentData();
|
||||
items.append(item);
|
||||
|
||||
item.first = QCanBusDevice::ReceiveOwnKey;
|
||||
item.second = ui->receivOwnComboBox->currentData();
|
||||
items.append(item);
|
||||
|
||||
item.first = QCanBusDevice::CanFdKey;
|
||||
item.second = ui->canFdComboBox->currentData();
|
||||
items.append(item);
|
||||
|
||||
item.first = QCanBusDevice::BitRateKey;
|
||||
item.second = ui->bitrateComboBox->currentData();
|
||||
items.append(item);
|
||||
|
||||
item.first = QCanBusDevice::DataBitRateKey;
|
||||
item.second = ui->dataBitrateComboBox->currentData();
|
||||
items.append(item);
|
||||
|
||||
return items;
|
||||
}
|
||||
|
||||
void xToolsCanBusStudioUi::setBitRates(QComboBox* cb, bool isFlexibleDataRateEnable)
|
||||
{
|
||||
if (!cb) {
|
||||
return;
|
||||
}
|
||||
|
||||
const QVector<int> rates = {10000, 20000, 50000, 100000, 125000, 250000, 500000, 800000, 1000000};
|
||||
|
||||
const QVector<int> dataRates = {2000000, 4000000, 8000000};
|
||||
|
||||
cb->clear();
|
||||
|
||||
for (int rate : rates) {
|
||||
cb->addItem(QString::number(rate), rate);
|
||||
}
|
||||
|
||||
if (isFlexibleDataRateEnable) {
|
||||
for (int rate : dataRates) {
|
||||
cb->addItem(QString::number(rate), rate);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,108 +0,0 @@
|
||||
/***************************************************************************************************
|
||||
* Copyright 2023-2024 x-tools-author(x-tools@outlook.com). All rights reserved.
|
||||
*
|
||||
* The file is encoded using "utf8 with bom", it is a part of xTools project.
|
||||
*
|
||||
* xTools is licensed according to the terms in the file LICENCE(GPL V3) in the root of the source
|
||||
* code directory.
|
||||
**************************************************************************************************/
|
||||
#pragma once
|
||||
|
||||
#include <QCanBusDevice>
|
||||
#include <QCanBusFrame>
|
||||
#include <QCheckBox>
|
||||
#include <QComboBox>
|
||||
#include <QSettings>
|
||||
#include <QVector>
|
||||
#include <QWidget>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
namespace Ui {
|
||||
class xToolsCanBusStudioUi;
|
||||
}
|
||||
QT_END_NAMESPACE
|
||||
|
||||
class xToolsCanBusStudioUi : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
typedef QPair<QCanBusDevice::ConfigurationKey, QVariant> ConfigurationItem;
|
||||
|
||||
public:
|
||||
Q_INVOKABLE xToolsCanBusStudioUi(QWidget *parent = Q_NULLPTR);
|
||||
~xToolsCanBusStudioUi();
|
||||
|
||||
private:
|
||||
struct
|
||||
{
|
||||
const QString pluginIndex = "CANStudio/pluginIndex";
|
||||
|
||||
const QString interfaceName = "CANStudio/interfaceName";
|
||||
const QString customConfiguration = "CANStudio/customConfiguration";
|
||||
const QString loopback = "CANStudio/loopback";
|
||||
const QString receiveOwn = "CANStudio/receiveOwn";
|
||||
const QString canFd = "CANStudio/canFd";
|
||||
const QString bitrate = "CANStudio/bitrate";
|
||||
const QString dataBitRate = "CANStudio/dataBitRate";
|
||||
const QString customBitRate = "CANStudio/customBitRate";
|
||||
const QString customDataBitRate = "CANStudio/customDataBitRate";
|
||||
|
||||
const QString frameTypeIndex = "CANStudio/frameTypeIndex";
|
||||
const QString extendedFormat = "CANStudio/extendedFormat";
|
||||
const QString flexibleDataRate = "CANStudio/fleibleDataRate";
|
||||
const QString bitrateSwitch = "CANStudio/bitrateSwitch";
|
||||
} mSettingKeyCtx;
|
||||
|
||||
private:
|
||||
Ui::xToolsCanBusStudioUi *ui;
|
||||
QSettings *mSettings{nullptr};
|
||||
QCanBusDevice *mDevice{nullptr};
|
||||
|
||||
private:
|
||||
void initUi();
|
||||
void initUiSelectPlugin();
|
||||
void initUiSpecifyConfiguration();
|
||||
void initUiCanFrame();
|
||||
void initUiSendCanFrame();
|
||||
|
||||
void initSetting();
|
||||
void initSettingSelectPlugin();
|
||||
void initSettingSpecifyConfiguration();
|
||||
void initSettingCanFrame();
|
||||
void initSettingSendCanFrame();
|
||||
|
||||
// These are slots.
|
||||
void onPluginChanged();
|
||||
void onDisconnectClicked();
|
||||
void onConnectClicked();
|
||||
|
||||
void onCustomConfigurationChanged();
|
||||
void onLoopbackIndexChanged(int index);
|
||||
void onReceiveOwnIndexChanged(int index);
|
||||
void onCanFdIndexChanged(int index);
|
||||
void onBitrateChanged(int index);
|
||||
void onDataBitrateChanged(int index);
|
||||
void onCustomBitrateChanged();
|
||||
void onCustomDataBitrateChanged();
|
||||
|
||||
void onFrameTypeChanged();
|
||||
void onExtendedFormatChanged();
|
||||
void onFlexibleDataRateChanged();
|
||||
void onBitrateSwitchChanged();
|
||||
|
||||
void onSendButtonClicked();
|
||||
|
||||
// Slots about CAN bus device
|
||||
void onErrorOccure(QCanBusDevice::CanBusError error);
|
||||
void onFrameReceived();
|
||||
void onFrameWritten(qint64 framesCount);
|
||||
|
||||
private:
|
||||
void setOptions(QComboBox *cb, bool usingUnspecified);
|
||||
void setCurrentIndex(QComboBox *cb, const QString &key);
|
||||
void setBitRates(QComboBox *cb, bool isFlexibleDataRateEnable);
|
||||
void setChecked(QCheckBox *cb, const QString &key);
|
||||
void setCustomConfigurationEnable(bool enable);
|
||||
void outputMessage(const QString &msg);
|
||||
void updateUiState(bool connected);
|
||||
QVector<ConfigurationItem> configurationItems();
|
||||
};
|
||||
@ -1,329 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>xToolsCanBusStudioUi</class>
|
||||
<widget class="QWidget" name="xToolsCanBusStudioUi">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>691</width>
|
||||
<height>634</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>CANBus Studio</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_2">
|
||||
<item row="4" column="0" rowspan="2">
|
||||
<widget class="QGroupBox" name="groupBox_4">
|
||||
<property name="title">
|
||||
<string>CAN frame</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_4">
|
||||
<item row="3" column="0" colspan="2">
|
||||
<widget class="QCheckBox" name="bitrateSwitchCheckBox">
|
||||
<property name="text">
|
||||
<string>Bitrate switch</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_9">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Frame type</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0" colspan="2">
|
||||
<widget class="QCheckBox" name="flexibleDataRateCheckBox">
|
||||
<property name="text">
|
||||
<string>Flexible data-rate</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QComboBox" name="frameTypeComboBox"/>
|
||||
</item>
|
||||
<item row="1" column="0" colspan="2">
|
||||
<widget class="QCheckBox" name="extendedFormatCheckBox">
|
||||
<property name="text">
|
||||
<string>Extended format</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="1">
|
||||
<widget class="QGroupBox" name="groupBox_2">
|
||||
<property name="title">
|
||||
<string>Send CAN frame</string>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>Frame ID</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QComboBox" name="frameIdComboBox">
|
||||
<property name="editable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string>Payload</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QComboBox" name="payloadComboBox">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="editable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="sendPushButton">
|
||||
<property name="text">
|
||||
<string>Send</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="0" column="1" rowspan="5">
|
||||
<widget class="QTabWidget" name="tabWidget">
|
||||
<property name="currentIndex">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<widget class="QWidget" name="tab">
|
||||
<attribute name="title">
|
||||
<string>Console</string>
|
||||
</attribute>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QTextBrowser" name="textBrowser"/>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QGroupBox" name="groupBox">
|
||||
<property name="title">
|
||||
<string>Select plugin</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="0" column="0" colspan="2">
|
||||
<widget class="QComboBox" name="pluginComboBox"/>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QPushButton" name="disconnectPushButton">
|
||||
<property name="text">
|
||||
<string>Disconnect</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QPushButton" name="connectPushButton">
|
||||
<property name="text">
|
||||
<string>Connect</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QGroupBox" name="groupBox_3">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="title">
|
||||
<string>Specify configuration</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_3">
|
||||
<item row="10" column="0" colspan="2">
|
||||
<widget class="QCheckBox" name="customDataBitrateCheckBox">
|
||||
<property name="text">
|
||||
<string>Custom data bitrate</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="8" column="1">
|
||||
<widget class="QComboBox" name="dataBitrateComboBox"/>
|
||||
</item>
|
||||
<item row="7" column="1">
|
||||
<widget class="QComboBox" name="bitrateComboBox"/>
|
||||
</item>
|
||||
<item row="9" column="0" colspan="2">
|
||||
<widget class="QCheckBox" name="customBitrateCheckBox">
|
||||
<property name="text">
|
||||
<string>Custom bitrate</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QComboBox" name="errorFilterComboBox">
|
||||
<property name="editable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="0">
|
||||
<widget class="QLabel" name="label_8">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>CAN FD</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="label_4">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Loopback</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="7" column="0">
|
||||
<widget class="QLabel" name="label_7">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Bitrate</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QComboBox" name="interfaceNameComboBox">
|
||||
<property name="editable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QComboBox" name="loopbackComboBox"/>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_6">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Interface</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="1">
|
||||
<widget class="QComboBox" name="canFdComboBox"/>
|
||||
</item>
|
||||
<item row="8" column="0">
|
||||
<widget class="QLabel" name="label_10">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Data bitrate</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1">
|
||||
<widget class="QComboBox" name="receivOwnComboBox"/>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<widget class="QLabel" name="label_5">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Receive own</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Error filter</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0" colspan="2">
|
||||
<widget class="QCheckBox" name="customConfigurationCheckBox">
|
||||
<property name="text">
|
||||
<string>Custom configurations</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
@ -1,25 +0,0 @@
|
||||
file(GLOB_RECURSE SOURCES_H "${CMAKE_SOURCE_DIR}/Source/CANBusStudio/*.h")
|
||||
file(GLOB_RECURSE SOURCES_UI "${CMAKE_SOURCE_DIR}/Source/CANBusStudio/*.ui")
|
||||
file(GLOB_RECURSE SOURCES_CPP "${CMAKE_SOURCE_DIR}/Source/CANBusStudio/*.cpp")
|
||||
|
||||
list(APPEND ALL_SOURCE ${SOURCES_H})
|
||||
list(APPEND ALL_SOURCE ${SOURCES_UI})
|
||||
list(APPEND ALL_SOURCE ${SOURCES_CPP})
|
||||
list(APPEND ALL_SOURCE ${CMAKE_SOURCE_DIR}/Source/Common/Common/xToolsSettings.h)
|
||||
list(APPEND ALL_SOURCE ${CMAKE_SOURCE_DIR}/Source/Common/Common/xToolsSettings.cpp)
|
||||
list(APPEND ALL_SOURCE ${CMAKE_SOURCE_DIR}/Source/Common/Common/xToolsInterface.h)
|
||||
list(APPEND ALL_SOURCE ${CMAKE_SOURCE_DIR}/Source/Common/Common/xToolsInterface.cpp)
|
||||
list(APPEND ALL_SOURCE ${CMAKE_SOURCE_DIR}/Source/Common/Common/xToolsTranslator.h)
|
||||
list(APPEND ALL_SOURCE ${CMAKE_SOURCE_DIR}/Source/Common/Common/xToolsTranslator.cpp)
|
||||
list(APPEND ALL_SOURCE ${CMAKE_SOURCE_DIR}/Source/Common/CommonUI/xToolsUi.h)
|
||||
list(APPEND ALL_SOURCE ${CMAKE_SOURCE_DIR}/Source/Common/CommonUI/xToolsMainWindow.h)
|
||||
list(APPEND ALL_SOURCE ${CMAKE_SOURCE_DIR}/Source/Common/CommonUI/xToolsMainWindow.cpp)
|
||||
list(APPEND ALL_SOURCE ${CMAKE_SOURCE_DIR}/xTools.qrc)
|
||||
|
||||
x_tools_add_executable("CANBusStudio" ${ALL_SOURCE})
|
||||
x_tools_set_target_properties(CANBusStudio)
|
||||
x_tools_deploy_qt(CANBusStudio)
|
||||
|
||||
target_link_libraries(CANBusStudio PRIVATE glog::glog)
|
||||
target_link_libraries(CANBusStudio PRIVATE Qt${QT_VERSION_MAJOR}::Widgets)
|
||||
target_link_libraries(CANBusStudio PRIVATE Qt${QT_VERSION_MAJOR}::SerialBus)
|
||||
@ -1,16 +0,0 @@
|
||||
/***************************************************************************************************
|
||||
* Copyright 2023-2024 x-tools-author(x-tools@outlook.com). All rights reserved.
|
||||
*
|
||||
* The file is encoded using "utf8 with bom", it is a part of xTools project.
|
||||
*
|
||||
* xTools is licensed according to the terms in the file LICENCE(GPL V3) in the root of the source
|
||||
* code directory.
|
||||
**************************************************************************************************/
|
||||
#include "xToolsCanBusStudioUi.h"
|
||||
#include "xToolsUi.h"
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
const QString appName = QObject::tr("CAN Bus Studio");
|
||||
return xToolsExec<xToolsCanBusStudioUi>(argc, argv, appName);
|
||||
}
|
||||
@ -1,149 +0,0 @@
|
||||
/***************************************************************************************************
|
||||
* Copyright 2023-2024 x-tools-author(x-tools@outlook.com). All rights reserved.
|
||||
*
|
||||
* The file is encoded using "utf8 with bom", it is a part of xTools project.
|
||||
*
|
||||
* xTools is licensed according to the terms in the file LICENCE(GPL V3) in the root of the source
|
||||
* code directory.
|
||||
**************************************************************************************************/
|
||||
#include "xToolsBleScanner.h"
|
||||
|
||||
#include <QBluetoothDeviceInfo>
|
||||
#include <QDebug>
|
||||
#include <QtGlobal>
|
||||
|
||||
#define BLE_ERR_SIG void (QBluetoothDeviceDiscoveryAgent::*)(QBluetoothDeviceDiscoveryAgent::Error)
|
||||
|
||||
xToolsBleScanner::xToolsBleScanner(QObject* parent)
|
||||
: QThread(parent)
|
||||
, m_discover(Q_NULLPTR)
|
||||
{}
|
||||
|
||||
xToolsBleScanner::~xToolsBleScanner() {}
|
||||
|
||||
void xToolsBleScanner::startDiscover()
|
||||
{
|
||||
start();
|
||||
}
|
||||
|
||||
void xToolsBleScanner::stopDiscover()
|
||||
{
|
||||
exit();
|
||||
}
|
||||
|
||||
bool xToolsBleScanner::isActive()
|
||||
{
|
||||
return isRunning();
|
||||
}
|
||||
|
||||
QVariant xToolsBleScanner::deviceInfo(int index)
|
||||
{
|
||||
m_deviceInfoListMutex.lock();
|
||||
if (index >= 0 && index < m_deviceInfoList.length()) {
|
||||
QBluetoothDeviceInfo info = m_deviceInfoList.at(index);
|
||||
return QVariant::fromValue<QBluetoothDeviceInfo>(info);
|
||||
}
|
||||
m_deviceInfoListMutex.unlock();
|
||||
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
QString xToolsBleScanner::deviceName(const QVariant& deviceInfo)
|
||||
{
|
||||
auto cookedInfo = deviceInfo.value<QBluetoothDeviceInfo>();
|
||||
return cookedInfo.name();
|
||||
}
|
||||
|
||||
void xToolsBleScanner::run()
|
||||
{
|
||||
m_discover = new QBluetoothDeviceDiscoveryAgent();
|
||||
connect(m_discover,
|
||||
&QBluetoothDeviceDiscoveryAgent::finished,
|
||||
this,
|
||||
&xToolsBleScanner::onDiscoveryFinished);
|
||||
connect(m_discover,
|
||||
&QBluetoothDeviceDiscoveryAgent::errorOccurred,
|
||||
this,
|
||||
&xToolsBleScanner::onDiscoveryErrorOccurred);
|
||||
connect(m_discover,
|
||||
&QBluetoothDeviceDiscoveryAgent::deviceDiscovered,
|
||||
this,
|
||||
&xToolsBleScanner::onDiscoveryDeviceDiscovered);
|
||||
|
||||
// 10s-1minute
|
||||
int interval = m_timeoutInterval < 10 ? 10 : m_timeoutInterval;
|
||||
interval = interval > 120 ? 120 : interval;
|
||||
m_discover->setLowEnergyDiscoveryTimeout(interval * 1000);
|
||||
|
||||
m_deviceInfoListMutex.lock();
|
||||
m_deviceInfoList.clear();
|
||||
m_deviceInfoListMutex.unlock();
|
||||
m_discover->start(QBluetoothDeviceDiscoveryAgent::LowEnergyMethod);
|
||||
exec();
|
||||
}
|
||||
|
||||
void xToolsBleScanner::onDiscoveryFinished()
|
||||
{
|
||||
emit devicesInfoListChanged();
|
||||
exit();
|
||||
}
|
||||
|
||||
void xToolsBleScanner::onDiscoveryErrorOccurred(QBluetoothDeviceDiscoveryAgent::Error error)
|
||||
{
|
||||
Q_UNUSED(error);
|
||||
qWarning() << "QBluetoothDeviceDiscoveryAgent error:" << m_discover->errorString();
|
||||
exit();
|
||||
emit errorOccurred(m_discover->errorString());
|
||||
}
|
||||
|
||||
void xToolsBleScanner::onDiscoveryDeviceDiscovered(const QBluetoothDeviceInfo& info)
|
||||
{
|
||||
const QString name = info.name();
|
||||
qInfo() << "new ble device:" << name;
|
||||
|
||||
if (!m_nameFiltter.isEmpty()) {
|
||||
if (!name.contains(m_nameFiltter)) {
|
||||
qInfo() << "device is ignored:" << name;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
m_deviceInfoListMutex.lock();
|
||||
m_deviceInfoList.append(info);
|
||||
m_deviceInfoListMutex.unlock();
|
||||
emit deviceDiscovered(info);
|
||||
}
|
||||
|
||||
QVariantList xToolsBleScanner::devicesInfoList()
|
||||
{
|
||||
QVariantList list;
|
||||
m_deviceInfoListMutex.lock();
|
||||
for (auto& info : m_deviceInfoList) {
|
||||
list.append(QVariant::fromValue(info));
|
||||
}
|
||||
m_deviceInfoListMutex.unlock();
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
int xToolsBleScanner::timeoutInterval()
|
||||
{
|
||||
return m_timeoutInterval;
|
||||
}
|
||||
|
||||
void xToolsBleScanner::setTimeoutInterval(int interval)
|
||||
{
|
||||
m_timeoutInterval = interval;
|
||||
emit timeoutIntervalChanged();
|
||||
}
|
||||
|
||||
QString xToolsBleScanner::namefiltter()
|
||||
{
|
||||
return m_nameFiltter;
|
||||
}
|
||||
|
||||
void xToolsBleScanner::setNameFiltter(const QString& flag)
|
||||
{
|
||||
m_nameFiltter = flag;
|
||||
emit filtterNameChanged();
|
||||
}
|
||||
@ -1,71 +0,0 @@
|
||||
/***************************************************************************************************
|
||||
* Copyright 2023-2024 x-tools-author(x-tools@outlook.com). All rights reserved.
|
||||
*
|
||||
* The file is encoded using "utf8 with bom", it is a part of xTools project.
|
||||
*
|
||||
* xTools is licensed according to the terms in the file LICENCE(GPL V3) in the root of the source
|
||||
* code directory.
|
||||
**************************************************************************************************/
|
||||
#pragma once
|
||||
|
||||
#include <QBluetoothDeviceDiscoveryAgent>
|
||||
#include <QBluetoothDeviceInfo>
|
||||
#include <QLoggingCategory>
|
||||
#include <QMutex>
|
||||
#include <QThread>
|
||||
#include <QVariant>
|
||||
|
||||
class xToolsBleScanner : public QThread
|
||||
{
|
||||
Q_OBJECT
|
||||
// clang-format off
|
||||
Q_PROPERTY(QVariantList deviceInfoList READ devicesInfoList NOTIFY devicesInfoListChanged)
|
||||
Q_PROPERTY(int timeoutInterval READ timeoutInterval WRITE setTimeoutInterval NOTIFY timeoutIntervalChanged)
|
||||
Q_PROPERTY(QString namefiltter READ namefiltter WRITE setNameFiltter NOTIFY filtterNameChanged)
|
||||
// clang-format on
|
||||
public:
|
||||
explicit xToolsBleScanner(QObject *parent = nullptr);
|
||||
~xToolsBleScanner();
|
||||
|
||||
public:
|
||||
Q_INVOKABLE void startDiscover();
|
||||
Q_INVOKABLE void stopDiscover();
|
||||
Q_INVOKABLE bool isActive();
|
||||
|
||||
Q_INVOKABLE QVariant deviceInfo(int index);
|
||||
Q_INVOKABLE QString deviceName(const QVariant &deviceInfo);
|
||||
|
||||
signals:
|
||||
void deviceDiscovered(const QBluetoothDeviceInfo &info);
|
||||
void errorOccurred(const QString &errStr);
|
||||
|
||||
protected:
|
||||
virtual void run() override;
|
||||
|
||||
private:
|
||||
QBluetoothDeviceDiscoveryAgent *m_discover;
|
||||
QMutex m_deviceInfoListMutex;
|
||||
|
||||
private:
|
||||
void onDiscoveryFinished();
|
||||
void onDiscoveryErrorOccurred(QBluetoothDeviceDiscoveryAgent::Error error);
|
||||
void onDiscoveryDeviceDiscovered(const QBluetoothDeviceInfo &info);
|
||||
|
||||
public:
|
||||
QVariantList devicesInfoList();
|
||||
int timeoutInterval();
|
||||
void setTimeoutInterval(int interval);
|
||||
QString namefiltter();
|
||||
void setNameFiltter(const QString &flag);
|
||||
|
||||
signals:
|
||||
void devicesInfoListChanged();
|
||||
void enableRefreshChanged();
|
||||
void timeoutIntervalChanged();
|
||||
void filtterNameChanged();
|
||||
|
||||
private:
|
||||
QVector<QBluetoothDeviceInfo> m_deviceInfoList;
|
||||
int m_timeoutInterval{120};
|
||||
QString m_nameFiltter{""};
|
||||
};
|
||||
@ -1,101 +0,0 @@
|
||||
/***************************************************************************************************
|
||||
* Copyright 2023 x-tools-author(x-tools@outlook.com). All rights reserved.
|
||||
*
|
||||
* The file is encoded using "utf8 with bom", it is a part of xTools project.
|
||||
*
|
||||
* xTools is licensed according to the terms in the file LICENCE(GPL V3) in the root of the source
|
||||
* code directory.
|
||||
**************************************************************************************************/
|
||||
#include "xToolsBleDeviceInfoComboBox.h"
|
||||
|
||||
#include <QBluetoothDeviceInfo>
|
||||
#include <QMessageBox>
|
||||
|
||||
xToolsBleDeviceInfoComboBox::xToolsBleDeviceInfoComboBox(QWidget* parent)
|
||||
: xToolsComboBox(parent)
|
||||
, mScanner(Q_NULLPTR)
|
||||
{
|
||||
mScanner = new xToolsBleScanner(this);
|
||||
connect(mScanner, &xToolsBleScanner::finished, this, &xToolsBleDeviceInfoComboBox::onFinished);
|
||||
connect(mScanner, &xToolsBleScanner::started, this, &xToolsBleDeviceInfoComboBox::started);
|
||||
connect(mScanner,
|
||||
&xToolsBleScanner::deviceDiscovered,
|
||||
this,
|
||||
&xToolsBleDeviceInfoComboBox::onDeviceDiscovered);
|
||||
connect(mScanner,
|
||||
&xToolsBleScanner::errorOccurred,
|
||||
this,
|
||||
&xToolsBleDeviceInfoComboBox::onErrorOccurred);
|
||||
}
|
||||
|
||||
xToolsBleDeviceInfoComboBox::~xToolsBleDeviceInfoComboBox()
|
||||
{
|
||||
mScanner->stopDiscover();
|
||||
}
|
||||
|
||||
void xToolsBleDeviceInfoComboBox::startDiscover()
|
||||
{
|
||||
clear();
|
||||
mScanner->startDiscover();
|
||||
}
|
||||
|
||||
void xToolsBleDeviceInfoComboBox::stopDiscover()
|
||||
{
|
||||
mScanner->stopDiscover();
|
||||
}
|
||||
|
||||
bool xToolsBleDeviceInfoComboBox::isActive()
|
||||
{
|
||||
return mScanner->isActive();
|
||||
return false;
|
||||
}
|
||||
|
||||
void xToolsBleDeviceInfoComboBox::setTimeoutInterval(int interval)
|
||||
{
|
||||
#if 0
|
||||
mScanner->setTimeoutInterval(interval);
|
||||
#endif
|
||||
}
|
||||
|
||||
void xToolsBleDeviceInfoComboBox::setNameFiltter(const QString& filtter)
|
||||
{
|
||||
mScanner->setNameFiltter(filtter);
|
||||
}
|
||||
|
||||
void xToolsBleDeviceInfoComboBox::changeEvent(QEvent* event)
|
||||
{
|
||||
xToolsComboBox::changeEvent(event);
|
||||
if ((event->type() == QEvent::EnabledChange) && isEnabled()) {
|
||||
onFinished();
|
||||
}
|
||||
}
|
||||
|
||||
void xToolsBleDeviceInfoComboBox::onFinished()
|
||||
{
|
||||
if (!isEnabled()) {
|
||||
return;
|
||||
}
|
||||
|
||||
clear();
|
||||
auto infos = mScanner->devicesInfoList();
|
||||
for (auto& info : infos) {
|
||||
QString name = mScanner->deviceName(info);
|
||||
addItem(name, info);
|
||||
}
|
||||
|
||||
emit finished();
|
||||
}
|
||||
|
||||
void xToolsBleDeviceInfoComboBox::onDeviceDiscovered(const QBluetoothDeviceInfo& info)
|
||||
{
|
||||
if (!isEnabled()) {
|
||||
return;
|
||||
}
|
||||
|
||||
addItem(info.name(), QVariant::fromValue(info));
|
||||
}
|
||||
|
||||
void xToolsBleDeviceInfoComboBox::onErrorOccurred(const QString& errStr)
|
||||
{
|
||||
QMessageBox::warning(this, tr("Error Occurred"), errStr);
|
||||
}
|
||||
@ -1,42 +0,0 @@
|
||||
/***************************************************************************************************
|
||||
* Copyright 2023 x-tools-author(x-tools@outlook.com). All rights reserved.
|
||||
*
|
||||
* The file is encoded using "utf8 with bom", it is a part of xTools project.
|
||||
*
|
||||
* xTools is licensed according to the terms in the file LICENCE(GPL V3) in the root of the source
|
||||
* code directory.
|
||||
**************************************************************************************************/
|
||||
#pragma once
|
||||
|
||||
#include <QEvent>
|
||||
|
||||
#include "xToolsBleScanner.h"
|
||||
#include "xToolsComboBox.h"
|
||||
|
||||
class xToolsBleDeviceInfoComboBox : public xToolsComboBox
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
xToolsBleDeviceInfoComboBox(QWidget *parent = Q_NULLPTR);
|
||||
~xToolsBleDeviceInfoComboBox();
|
||||
void startDiscover();
|
||||
void stopDiscover();
|
||||
bool isActive();
|
||||
void setTimeoutInterval(int interval);
|
||||
void setNameFiltter(const QString &filtter);
|
||||
|
||||
signals:
|
||||
void finished();
|
||||
void started();
|
||||
|
||||
protected:
|
||||
virtual void changeEvent(QEvent *event) override;
|
||||
|
||||
private:
|
||||
xToolsBleScanner *mScanner;
|
||||
|
||||
private slots:
|
||||
void onFinished();
|
||||
void onDeviceDiscovered(const QBluetoothDeviceInfo &info);
|
||||
void onErrorOccurred(const QString &errStr);
|
||||
};
|
||||
@ -1,27 +0,0 @@
|
||||
file(GLOB_RECURSE SOURCE_H "${CMAKE_SOURCE_DIR}/Source/ModbusStudio/*.h")
|
||||
file(GLOB_RECURSE SOURCE_UI "${CMAKE_SOURCE_DIR}/Source/ModbusStudio/*.ui")
|
||||
file(GLOB_RECURSE SOURCE_CPP "${CMAKE_SOURCE_DIR}/Source/ModbusStudio/*.cpp")
|
||||
|
||||
list(APPEND ALL_SOURCE ${SOURCE_H})
|
||||
list(APPEND ALL_SOURCE ${SOURCE_UI})
|
||||
list(APPEND ALL_SOURCE ${SOURCE_CPP})
|
||||
list(APPEND ALL_SOURCE ${CMAKE_SOURCE_DIR}/Source/Common/Common/xToolsSettings.h)
|
||||
list(APPEND ALL_SOURCE ${CMAKE_SOURCE_DIR}/Source/Common/Common/xToolsSettings.cpp)
|
||||
list(APPEND ALL_SOURCE ${CMAKE_SOURCE_DIR}/Source/Common/Common/xToolsInterface.h)
|
||||
list(APPEND ALL_SOURCE ${CMAKE_SOURCE_DIR}/Source/Common/Common/xToolsInterface.cpp)
|
||||
list(APPEND ALL_SOURCE ${CMAKE_SOURCE_DIR}/Source/Common/Common/xToolsTranslator.h)
|
||||
list(APPEND ALL_SOURCE ${CMAKE_SOURCE_DIR}/Source/Common/Common/xToolsTranslator.cpp)
|
||||
list(APPEND ALL_SOURCE ${CMAKE_SOURCE_DIR}/Source/Common/CommonUI/xToolsUi.h)
|
||||
list(APPEND ALL_SOURCE ${CMAKE_SOURCE_DIR}/Source/Common/CommonUI/xToolsMainWindow.h)
|
||||
list(APPEND ALL_SOURCE ${CMAKE_SOURCE_DIR}/Source/Common/CommonUI/xToolsMainWindow.cpp)
|
||||
list(APPEND ALL_SOURCE ${CMAKE_SOURCE_DIR}/xTools.qrc)
|
||||
|
||||
x_tools_add_executable("ModbusStudio" ${ALL_SOURCE})
|
||||
x_tools_set_target_properties(ModbusStudio)
|
||||
x_tools_deploy_qt(ModbusStudio)
|
||||
|
||||
target_link_libraries(ModbusStudio PRIVATE glog::glog)
|
||||
target_link_libraries(ModbusStudio PRIVATE Qt${QT_VERSION_MAJOR}::Widgets)
|
||||
target_link_libraries(ModbusStudio PRIVATE Qt${QT_VERSION_MAJOR}::Network)
|
||||
target_link_libraries(ModbusStudio PRIVATE Qt${QT_VERSION_MAJOR}::SerialBus)
|
||||
target_link_libraries(ModbusStudio PRIVATE Qt${QT_VERSION_MAJOR}::SerialPort)
|
||||
@ -1,346 +0,0 @@
|
||||
/***************************************************************************************************
|
||||
* Copyright 2023-2024 x-tools-author(x-tools@outlook.com). All rights reserved.
|
||||
*
|
||||
* The file is encoded using "utf8 with bom", it is a part of xTools project.
|
||||
*
|
||||
* xTools is licensed according to the terms in the file LICENCE(GPL V3) in the root of the source
|
||||
* code directory.
|
||||
**************************************************************************************************/
|
||||
#include "xToolsModbusStudio.h"
|
||||
|
||||
#include <QCoreApplication>
|
||||
#include <QDebug>
|
||||
#include <QModbusTcpClient>
|
||||
#include <QModbusTcpServer>
|
||||
#if QT_VERSION < QT_VERSION_CHECK(6, 2, 0)
|
||||
#include <QModbusRtuSerialMaster>
|
||||
#include <QModbusRtuSerialSlave>
|
||||
#else
|
||||
#include <QModbusRtuSerialClient>
|
||||
#include <QModbusRtuSerialServer>
|
||||
#endif
|
||||
|
||||
xToolsModbusStudio::xToolsModbusStudio(QObject *parent)
|
||||
: QObject(parent)
|
||||
{}
|
||||
|
||||
xToolsModbusStudio::~xToolsModbusStudio() {}
|
||||
|
||||
xToolsModbusStudio *xToolsModbusStudio::Instance()
|
||||
{
|
||||
static xToolsModbusStudio *factory = Q_NULLPTR;
|
||||
|
||||
if (!factory) {
|
||||
factory = new xToolsModbusStudio(qApp);
|
||||
}
|
||||
|
||||
return factory;
|
||||
}
|
||||
|
||||
const QString xToolsModbusStudio::TypeName(int type)
|
||||
{
|
||||
if (type == kModbusRtuSerialClient) {
|
||||
return tr("RTU Client");
|
||||
} else if (type == kModbusRtuSerialServer) {
|
||||
return tr("RTU Server");
|
||||
} else if (type == kModbusTcpClient) {
|
||||
return tr("TCP Client");
|
||||
} else if (type == kModbusTcpServer) {
|
||||
return tr("TCP Server");
|
||||
}
|
||||
|
||||
Q_ASSERT_X(false, __FUNCTION__, "Unknown modebus device type");
|
||||
qWarning() << "Unknown modebus device type";
|
||||
|
||||
return "Unknown";
|
||||
}
|
||||
|
||||
QModbusDevice *xToolsModbusStudio::CreateDevice(int type)
|
||||
{
|
||||
if (type == kModbusRtuSerialClient) {
|
||||
qInfo() << "Create rtu serial client.";
|
||||
#if QT_VERSION < QT_VERSION_CHECK(6, 2, 0)
|
||||
return new QModbusRtuSerialMaster(this);
|
||||
#else
|
||||
return new QModbusRtuSerialClient(this);
|
||||
#endif
|
||||
} else if (type == kModbusRtuSerialServer) {
|
||||
qInfo() << "Create rtu serial server.";
|
||||
#if QT_VERSION < QT_VERSION_CHECK(6, 2, 0)
|
||||
return new QModbusRtuSerialSlave(this);
|
||||
#else
|
||||
return new QModbusRtuSerialServer(this);
|
||||
#endif
|
||||
} else if (type == kModbusTcpClient) {
|
||||
qInfo() << "Create tcp client.";
|
||||
return new QModbusTcpClient();
|
||||
} else if (type == kModbusTcpServer) {
|
||||
qInfo() << "Create tcp server.";
|
||||
return new QModbusTcpServer();
|
||||
}
|
||||
|
||||
Q_ASSERT_X(false, __FUNCTION__, "Unknown modebus device type");
|
||||
qWarning() << "Unknown modebus device type";
|
||||
|
||||
return Q_NULLPTR;
|
||||
}
|
||||
|
||||
bool xToolsModbusStudio::IsTcpDevice(QModbusDevice *modbus_device)
|
||||
{
|
||||
if (modbus_device) {
|
||||
if (qobject_cast<QModbusTcpClient *>(modbus_device)) {
|
||||
return true;
|
||||
} else if (qobject_cast<QModbusTcpServer *>(modbus_device)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool xToolsModbusStudio::IsRtuSerialDevice(QModbusDevice *modbus_device)
|
||||
{
|
||||
if (modbus_device) {
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(6, 2, 0)
|
||||
if (qobject_cast<QModbusRtuSerialClient *>(modbus_device)) {
|
||||
#else
|
||||
if (qobject_cast<QModbusRtuSerialMaster *>(modbus_device)) {
|
||||
#endif
|
||||
return true;
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(6, 2, 0)
|
||||
} else if (qobject_cast<QModbusRtuSerialServer *>(modbus_device)) {
|
||||
#else
|
||||
} else if (qobject_cast<QModbusRtuSerialSlave *>(modbus_device)) {
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool xToolsModbusStudio::IsTcpDeviceType(int type)
|
||||
{
|
||||
bool is_tcp = (type == kModbusTcpClient);
|
||||
is_tcp |= (type == kModbusTcpServer);
|
||||
|
||||
return is_tcp;
|
||||
}
|
||||
|
||||
bool xToolsModbusStudio::IsRtuSerialDeviceType(int type)
|
||||
{
|
||||
bool is_rtu = (type == kModbusRtuSerialClient);
|
||||
is_rtu |= (type == kModbusRtuSerialServer);
|
||||
|
||||
return is_rtu;
|
||||
}
|
||||
|
||||
bool xToolsModbusStudio::IsServerDevice(QModbusDevice *modbus_device)
|
||||
{
|
||||
if (modbus_device && qobject_cast<QModbusServer *>(modbus_device)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool xToolsModbusStudio::IsClientDevice(QModbusDevice *modbus_device)
|
||||
{
|
||||
if (modbus_device && qobject_cast<QModbusClient *>(modbus_device)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool xToolsModbusStudio::ConnectDeivce(QModbusDevice *modbus_device)
|
||||
{
|
||||
if (modbus_device) {
|
||||
return modbus_device->connectDevice();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool xToolsModbusStudio::IsConnected(QModbusDevice *modbus_device)
|
||||
{
|
||||
if (modbus_device) {
|
||||
if (modbus_device->state() == QModbusDevice::ConnectedState) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool xToolsModbusStudio::IsValidModbusReply(QModbusReply *reply)
|
||||
{
|
||||
if (reply && !reply->isFinished()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool xToolsModbusStudio::SetServerData(QModbusDevice *server,
|
||||
QModbusDataUnit::RegisterType table,
|
||||
int address,
|
||||
int data,
|
||||
bool enable_log)
|
||||
{
|
||||
bool is_ok = false;
|
||||
if (server && qobject_cast<QModbusServer *>(server)) {
|
||||
QModbusServer *modbusServer = qobject_cast<QModbusServer *>(server);
|
||||
is_ok = modbusServer->setData(table, address, data);
|
||||
if (enable_log) {
|
||||
qInfo() << "Set register data result:" << is_ok << "table:" << table
|
||||
<< "address:" << address << "data:" << data;
|
||||
}
|
||||
}
|
||||
|
||||
return is_ok;
|
||||
}
|
||||
|
||||
QList<quint16> xToolsModbusStudio::GetServerData(QModbusDevice *server,
|
||||
QModbusDataUnit::RegisterType table,
|
||||
int address,
|
||||
int quantity)
|
||||
{
|
||||
QList<quint16> values;
|
||||
if (server && qobject_cast<QModbusServer *>(server)) {
|
||||
QModbusServer *cooked_server = qobject_cast<QModbusServer *>(server);
|
||||
for (int i = address; i < quantity; i++) {
|
||||
quint16 value;
|
||||
if (cooked_server->data(table, i, &value)) {
|
||||
values.append(value);
|
||||
} else {
|
||||
qWarning() << "Parameters error!";
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
qWarning() << "Can not get values from null object!";
|
||||
}
|
||||
|
||||
return values;
|
||||
}
|
||||
|
||||
void xToolsModbusStudio::DeleteModbusDevuce(QModbusDevice **modbus_device)
|
||||
{
|
||||
if (*modbus_device) {
|
||||
QModbusServer *server = qobject_cast<QModbusServer *>(*modbus_device);
|
||||
if (server) {
|
||||
server->disconnect();
|
||||
}
|
||||
|
||||
(*modbus_device)->deleteLater();
|
||||
(*modbus_device) = Q_NULLPTR;
|
||||
}
|
||||
}
|
||||
|
||||
QModbusDevice *xToolsModbusStudio::CreateRtuSerialDevice(
|
||||
int type, const QString &port_name, int parity, int baud_rate, int data_bits, int stop_bits)
|
||||
{
|
||||
QModbusDevice *device = CreateDevice(type);
|
||||
if (IsRtuSerialDevice(device)) {
|
||||
device->setConnectionParameter(QModbusDevice::SerialPortNameParameter, port_name);
|
||||
device->setConnectionParameter(QModbusDevice::SerialBaudRateParameter, baud_rate);
|
||||
device->setConnectionParameter(QModbusDevice::SerialDataBitsParameter, data_bits);
|
||||
device->setConnectionParameter(QModbusDevice::SerialStopBitsParameter, stop_bits);
|
||||
device->setConnectionParameter(QModbusDevice::SerialParityParameter, parity);
|
||||
|
||||
qInfo() << "Set rtu serial modbus device parameters:"
|
||||
<< "port name:" << port_name << "baud rate:" << baud_rate
|
||||
<< "data bits:" << data_bits << "stop bits" << stop_bits << "parity" << parity;
|
||||
}
|
||||
|
||||
return device;
|
||||
}
|
||||
|
||||
QModbusDevice *xToolsModbusStudio::CreateTcpDevice(int type, QString address, int port)
|
||||
{
|
||||
QModbusDevice *device = CreateDevice(type);
|
||||
if (IsTcpDevice(device)) {
|
||||
device->setConnectionParameter(QModbusDevice::NetworkAddressParameter, address);
|
||||
device->setConnectionParameter(QModbusDevice::NetworkPortParameter, port);
|
||||
|
||||
qInfo() << "Set tcp modbus device parameters:"
|
||||
<< "ip address:" << address << "port" << port;
|
||||
}
|
||||
|
||||
return device;
|
||||
}
|
||||
|
||||
void xToolsModbusStudio::SetClientDeviceParameters(QModbusDevice *client,
|
||||
int timeout,
|
||||
int number_of_retries)
|
||||
{
|
||||
if (client) {
|
||||
qInfo() << "Set modbus client device parameters:"
|
||||
<< "timeout:" << timeout << "number_of_retries" << number_of_retries;
|
||||
|
||||
QModbusClient *cooked_client = qobject_cast<QModbusClient *>(client);
|
||||
cooked_client->setTimeout(timeout);
|
||||
cooked_client->setNumberOfRetries(number_of_retries);
|
||||
}
|
||||
}
|
||||
|
||||
void xToolsModbusStudio::SetServerDeviceParameters(QModbusDevice *server,
|
||||
int address,
|
||||
bool device_busy,
|
||||
bool listen_only_mode)
|
||||
{
|
||||
if (server) {
|
||||
qInfo() << "Set modbus server device parameters:"
|
||||
<< "address:" << address << "device busy" << device_busy
|
||||
<< "listen only mode:" << listen_only_mode;
|
||||
|
||||
QModbusServer *cooked_server = qobject_cast<QModbusServer *>(server);
|
||||
cooked_server->setServerAddress(address);
|
||||
cooked_server->setValue(QModbusServer::DeviceBusy, device_busy);
|
||||
cooked_server->setValue(QModbusServer::ListenOnlyMode, listen_only_mode);
|
||||
}
|
||||
}
|
||||
|
||||
QModbusReply *xToolsModbusStudio::SendWriteRequest(QModbusDevice *modbus_device,
|
||||
int register_type,
|
||||
int start_address,
|
||||
#if QT_VERSION < QT_VERSION_CHECK(6, 2, 0)
|
||||
QVector<quint16> values,
|
||||
#else
|
||||
QList<quint16> values,
|
||||
#endif
|
||||
int server_address)
|
||||
{
|
||||
if (modbus_device && IsClientDevice(modbus_device)) {
|
||||
auto cooked_type = QModbusDataUnit::RegisterType(register_type);
|
||||
QModbusDataUnit dataUnit(cooked_type, start_address, values);
|
||||
if (dataUnit.isValid()) {
|
||||
qInfo() << "register-type:" << register_type << " start-address:" << start_address
|
||||
<< " serverAddress:" << server_address << " values:" << values;
|
||||
|
||||
auto *client = qobject_cast<QModbusClient *>(modbus_device);
|
||||
QModbusReply *reply = client->sendWriteRequest(dataUnit, server_address);
|
||||
return reply;
|
||||
} else {
|
||||
qWarning() << "Unvalid data unit!";
|
||||
}
|
||||
}
|
||||
|
||||
return Q_NULLPTR;
|
||||
}
|
||||
|
||||
QModbusReply *xToolsModbusStudio::SendRawRequest(QModbusDevice *modbus_device,
|
||||
int server_address,
|
||||
int function_code,
|
||||
const QByteArray &data)
|
||||
{
|
||||
auto cooked_function_code = QModbusPdu::FunctionCode(function_code);
|
||||
QModbusRequest request(cooked_function_code, data);
|
||||
if (IsClientDevice(modbus_device)) {
|
||||
QModbusClient *client = qobject_cast<QModbusClient *>(modbus_device);
|
||||
return client->sendRawRequest(request, server_address);
|
||||
}
|
||||
|
||||
return Q_NULLPTR;
|
||||
}
|
||||
@ -1,79 +0,0 @@
|
||||
/***************************************************************************************************
|
||||
* Copyright 2023-2024 x-tools-author(x-tools@outlook.com). All rights reserved.
|
||||
*
|
||||
* The file is encoded using "utf8 with bom", it is a part of xTools project.
|
||||
*
|
||||
* xTools is licensed according to the terms in the file LICENCE(GPL V3) in the root of the source
|
||||
* code directory.
|
||||
**************************************************************************************************/
|
||||
#pragma once
|
||||
|
||||
#include <QModbusDataUnit>
|
||||
#include <QModbusDevice>
|
||||
#include <QModbusReply>
|
||||
#include <QObject>
|
||||
|
||||
class xToolsModbusStudio : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
enum ModbusDeviceType {
|
||||
kModbusRtuSerialClient,
|
||||
kModbusRtuSerialServer,
|
||||
kModbusTcpClient,
|
||||
kModbusTcpServer
|
||||
};
|
||||
Q_ENUM(ModbusDeviceType)
|
||||
|
||||
private:
|
||||
xToolsModbusStudio(QObject *parent = Q_NULLPTR);
|
||||
|
||||
public:
|
||||
~xToolsModbusStudio();
|
||||
static xToolsModbusStudio *Instance();
|
||||
|
||||
public:
|
||||
const QString TypeName(int type);
|
||||
QModbusDevice *CreateDevice(int type);
|
||||
bool IsTcpDevice(QModbusDevice *modbus_device);
|
||||
bool IsRtuSerialDevice(QModbusDevice *modbus_device);
|
||||
bool IsTcpDeviceType(int type);
|
||||
bool IsRtuSerialDeviceType(int type);
|
||||
bool IsServerDevice(QModbusDevice *modbus_device);
|
||||
bool IsClientDevice(QModbusDevice *modbus_device);
|
||||
bool ConnectDeivce(QModbusDevice *modbus_device);
|
||||
bool IsConnected(QModbusDevice *modbus_device);
|
||||
bool IsValidModbusReply(QModbusReply *reply);
|
||||
bool SetServerData(QModbusDevice *server,
|
||||
QModbusDataUnit::RegisterType table,
|
||||
int address,
|
||||
int data,
|
||||
bool enable_log = true);
|
||||
QList<quint16> GetServerData(QModbusDevice *server,
|
||||
QModbusDataUnit::RegisterType table,
|
||||
int address,
|
||||
int quantity);
|
||||
void DeleteModbusDevuce(QModbusDevice **modbus_device);
|
||||
|
||||
QModbusDevice *CreateRtuSerialDevice(
|
||||
int type, const QString &port_name, int parity, int baud_rate, int data_bits, int stop_bits);
|
||||
QModbusDevice *CreateTcpDevice(int deviceType, QString address, int port);
|
||||
void SetClientDeviceParameters(QModbusDevice *client, int timeout, int number_of_retries);
|
||||
void SetServerDeviceParameters(QModbusDevice *server,
|
||||
int address,
|
||||
bool device_busy,
|
||||
bool listen_only_mode);
|
||||
QModbusReply *SendWriteRequest(QModbusDevice *modbus_device,
|
||||
int register_type,
|
||||
int start_address,
|
||||
#if QT_VERSION < QT_VERSION_CHECK(6, 2, 0)
|
||||
QVector<quint16> values,
|
||||
#else
|
||||
QList<quint16> values,
|
||||
#endif
|
||||
int server_address);
|
||||
QModbusReply *SendRawRequest(QModbusDevice *modbus_device,
|
||||
int server_address,
|
||||
int function_code,
|
||||
const QByteArray &data);
|
||||
};
|
||||
File diff suppressed because it is too large
Load Diff
@ -1,134 +0,0 @@
|
||||
/***************************************************************************************************
|
||||
* Copyright 2023-2024 x-tools-author(x-tools@outlook.com). All rights reserved.
|
||||
*
|
||||
* The file is encoded using "utf8 with bom", it is a part of xTools project.
|
||||
*
|
||||
* xTools is licensed according to the terms in the file LICENCE(GPL V3) in the root of the source
|
||||
* code directory.
|
||||
**************************************************************************************************/
|
||||
#pragma once
|
||||
|
||||
#include <QJsonArray>
|
||||
#include <QLoggingCategory>
|
||||
#include <QModbusDataUnit>
|
||||
#include <QModbusDevice>
|
||||
#include <QModbusReply>
|
||||
#include <QModbusServer>
|
||||
#include <QSettings>
|
||||
#include <QStandardItemModel>
|
||||
#include <QTableView>
|
||||
#include <QVector>
|
||||
#include <QWidget>
|
||||
|
||||
namespace Ui {
|
||||
class xToolsModbusStudioUi;
|
||||
}
|
||||
|
||||
struct xToolsModbusUiSettingKeys;
|
||||
class xToolsModbusStudioUi : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit xToolsModbusStudioUi(QWidget *parent = Q_NULLPTR);
|
||||
~xToolsModbusStudioUi();
|
||||
|
||||
signals:
|
||||
void deviceChanged(QModbusDevice *device);
|
||||
|
||||
private:
|
||||
Ui::xToolsModbusStudioUi *ui;
|
||||
QModbusDevice *m_modbusDevice{Q_NULLPTR};
|
||||
QSettings *m_settings{Q_NULLPTR};
|
||||
QStandardItemModel *m_registerModel{Q_NULLPTR};
|
||||
xToolsModbusUiSettingKeys *m_keyCtx;
|
||||
|
||||
private:
|
||||
void initComponents();
|
||||
void initComponentDevices();
|
||||
void initComponentAddress();
|
||||
void initComponentPortName();
|
||||
void initComponnetBaudRate();
|
||||
void initComponnetDataBits();
|
||||
void initComponnetStopBits();
|
||||
void initComponnetParity();
|
||||
void initComponentFunctionCode();
|
||||
void initComponentRegisterTableView();
|
||||
void initComponentInput();
|
||||
void initComponentRegisterTabWidget();
|
||||
|
||||
void initSettings();
|
||||
void initSettingsDevice();
|
||||
void initSettingsNetwork();
|
||||
void initSettingsSerialPort();
|
||||
void initSettingsClient();
|
||||
void initSettingsServer();
|
||||
void initSettingsClientOperations();
|
||||
void initSettingsInput();
|
||||
|
||||
void initSignals();
|
||||
void initSignalsDevice();
|
||||
void initSignalsNetworking();
|
||||
void initSignalsSerialPort();
|
||||
void initSignalsClient();
|
||||
void initSignalsServer();
|
||||
void initSignalsClientOperations();
|
||||
|
||||
void onErrorOccurred();
|
||||
void onDeviceTypeChanged();
|
||||
void onCloseClicked();
|
||||
void onOpenClicked();
|
||||
void onAddressChanged();
|
||||
void onPortChanged();
|
||||
void onCustomAddressChanged();
|
||||
void onPortNameChanged();
|
||||
void onParityChanged();
|
||||
void onBaudRateChanged();
|
||||
void onDataBitsChanged();
|
||||
void onStopBistChanged();
|
||||
void onInvokeRefresh();
|
||||
void onClientTimeoutChanged();
|
||||
void onClientRepeatTimeChanged();
|
||||
void onServerIsBusyChanged();
|
||||
void onServerJustListenChanged();
|
||||
void onServerAddressChanged();
|
||||
void onFunctionCodeChanged();
|
||||
void onTargetAddressChanged();
|
||||
void onStartAddressChanged();
|
||||
void onAddressNumberChanged();
|
||||
|
||||
void onReadClicked();
|
||||
void onWriteClicked();
|
||||
void onSendClicked();
|
||||
|
||||
void onDateWritten(QModbusDataUnit::RegisterType table, int address, int size);
|
||||
void onItemChanged(QStandardItem *item);
|
||||
|
||||
private:
|
||||
QModbusDevice *CreateModbusDevice();
|
||||
QTableView *CreateTableView(int rowCount, QTableView *tableView);
|
||||
|
||||
void updateUiState(bool connected);
|
||||
void updateClientTableView();
|
||||
void updateClientTableViewData(const QList<quint16> &values);
|
||||
void updateClientReadWriteButtonState();
|
||||
void updateClientParameters();
|
||||
void updateClientTableViewAddress(QTableView *view, int startAddress);
|
||||
void updateServerParameters();
|
||||
bool updateServerMap(QModbusDevice *server);
|
||||
void updateServerRegistersData();
|
||||
|
||||
quint8 getClientFunctionCode();
|
||||
QList<quint16> getClientRegisterValue();
|
||||
QByteArray getClientPdu();
|
||||
QTableView *getTableView(QModbusDataUnit::RegisterType table);
|
||||
QList<quint16> getTableValues(QTableView *tableView, int row, int count);
|
||||
|
||||
void outputModbusReply(QModbusReply *reply, int functionCode);
|
||||
void outputMessage(const QString &msg,
|
||||
bool isError,
|
||||
const QString &color = QString(),
|
||||
const QString &flag = QString());
|
||||
bool isConnected();
|
||||
bool writeSettingsArray(
|
||||
const QString &group, const QString &key, const QString &value, int index, int maxIndex);
|
||||
};
|
||||
@ -1,773 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>xToolsModbusStudioUi</class>
|
||||
<widget class="QWidget" name="xToolsModbusStudioUi">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>1022</width>
|
||||
<height>795</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string notr="true">Modbus Studio</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="0" column="0">
|
||||
<widget class="QWidget" name="widget" native="true">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>200</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_3">
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QWidget" name="widgetDeviceOperations" native="true">
|
||||
<layout class="QGridLayout" name="gridLayout_6">
|
||||
<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 row="0" column="0" colspan="2">
|
||||
<widget class="QLabel" name="label_7">
|
||||
<property name="font">
|
||||
<font>
|
||||
<italic>true</italic>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Device operations</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0" colspan="2">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_3">
|
||||
<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="QPushButton" name="cloese_button_">
|
||||
<property name="text">
|
||||
<string>CloseDevice</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="open_button_">
|
||||
<property name="text">
|
||||
<string>OpenDevice</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QComboBox" name="device_list_"/>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Device list</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0" colspan="2">
|
||||
<widget class="Line" name="line_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QWidget" name="widgetNetworkSettings" native="true">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_10">
|
||||
<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 row="2" column="1">
|
||||
<widget class="QComboBox" name="address_combo_box">
|
||||
<property name="editable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0" colspan="2">
|
||||
<widget class="QLabel" name="label_14">
|
||||
<property name="font">
|
||||
<font>
|
||||
<italic>true</italic>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Network settings</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Port</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QSpinBox" name="port_spin_box">
|
||||
<property name="maximum">
|
||||
<number>65535</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Address</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0" colspan="2">
|
||||
<widget class="Line" name="line_3">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QWidget" name="widgetSerialPortSettings" native="true">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_11">
|
||||
<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 row="0" column="0" colspan="2">
|
||||
<widget class="QLabel" name="label_15">
|
||||
<property name="font">
|
||||
<font>
|
||||
<italic>true</italic>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Serial port settings</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_8">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Port name</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="label_9">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Baud rate</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="1">
|
||||
<widget class="QComboBox" name="stop_bits_"/>
|
||||
</item>
|
||||
<item row="4" column="1">
|
||||
<widget class="QComboBox" name="data_bits_"/>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<widget class="QLabel" name="label_10">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Data bits</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QComboBox" name="port_name_"/>
|
||||
</item>
|
||||
<item row="6" column="1">
|
||||
<widget class="QComboBox" name="parity_"/>
|
||||
</item>
|
||||
<item row="6" column="0">
|
||||
<widget class="QLabel" name="label_12">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Parity</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="0">
|
||||
<widget class="QLabel" name="label_11">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Stop bits</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QComboBox" name="baud_rate_">
|
||||
<property name="editable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0" colspan="2">
|
||||
<widget class="Line" name="line_4">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QWidget" name="widgetServerParameters" native="true">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_12">
|
||||
<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 row="4" column="1">
|
||||
<widget class="QSpinBox" name="server_address">
|
||||
<property name="maximum">
|
||||
<number>265</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0" colspan="2">
|
||||
<widget class="QCheckBox" name="device_busy_">
|
||||
<property name="text">
|
||||
<string>Device busy</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<widget class="QLabel" name="label_6">
|
||||
<property name="text">
|
||||
<string>Server address</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0" colspan="2">
|
||||
<widget class="QLabel" name="label_16">
|
||||
<property name="font">
|
||||
<font>
|
||||
<italic>true</italic>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Server parameters</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0" colspan="2">
|
||||
<widget class="QCheckBox" name="listen_only_mode_">
|
||||
<property name="text">
|
||||
<string>Listen only mode</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0" colspan="2">
|
||||
<widget class="Line" name="line_5">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QWidget" name="widgetClientParameters" native="true">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>200</height>
|
||||
</size>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_13">
|
||||
<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 row="2" column="1">
|
||||
<widget class="QSpinBox" name="repeat_time_">
|
||||
<property name="minimum">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>3</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="1">
|
||||
<widget class="QSpinBox" name="device_address_">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>255</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="label_5">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Repeat times</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_4">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Timeout</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="0">
|
||||
<widget class="QLabel" name="label_17">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Function code</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="1">
|
||||
<widget class="QComboBox" name="function_code_">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Ignored" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>16777215</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="8" column="1">
|
||||
<widget class="QSpinBox" name="quantity_">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>128</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QSpinBox" name="timeout_">
|
||||
<property name="minimum">
|
||||
<number>500</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>10000</number>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<number>100</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>500</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="7" column="1">
|
||||
<widget class="QSpinBox" name="start_address_">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>65535</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="0">
|
||||
<widget class="QLabel" name="label_18">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Target address</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="7" column="0">
|
||||
<widget class="QLabel" name="label_19">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Start address</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0" colspan="2">
|
||||
<widget class="Line" name="line">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="8" column="0">
|
||||
<widget class="QLabel" name="label_20">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Address number</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="9" column="0" colspan="2">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<item>
|
||||
<widget class="QPushButton" name="read_">
|
||||
<property name="text">
|
||||
<string>Read</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="write_">
|
||||
<property name="text">
|
||||
<string>Write</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="1" column="0" colspan="2">
|
||||
<widget class="Line" name="line_6">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0" colspan="2">
|
||||
<widget class="QLabel" name="label_21">
|
||||
<property name="font">
|
||||
<font>
|
||||
<italic>true</italic>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Client parameters</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<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="QGroupBox" name="console_">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Expanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="title">
|
||||
<string>Colsole</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<item>
|
||||
<widget class="QTextBrowser" name="text_browser_"/>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="clientRegistersGroupBox">
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>16777215</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="title">
|
||||
<string>Client registers</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_7">
|
||||
<item row="0" column="0" colspan="2">
|
||||
<widget class="QTableView" name="client_registers_"/>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="clientCustomCommandGroupBox">
|
||||
<property name="title">
|
||||
<string>Custom command</string>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QLabel" name="label_13">
|
||||
<property name="text">
|
||||
<string>Protocol data unit</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QComboBox" name="pdu_">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="editable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="send_">
|
||||
<property name="text">
|
||||
<string>Send</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="registersGroupBox">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>250</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>16777215</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="title">
|
||||
<string>Server registers</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_9">
|
||||
<item row="0" column="0">
|
||||
<widget class="QTabWidget" name="server_registers_">
|
||||
<property name="currentIndex">
|
||||
<number>-1</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
@ -1,16 +0,0 @@
|
||||
/***************************************************************************************************
|
||||
* Copyright 2023-2024 x-tools-author(x-tools@outlook.com). All rights reserved.
|
||||
*
|
||||
* The file is encoded using "utf8 with bom", it is a part of xTools project.
|
||||
*
|
||||
* xTools is licensed according to the terms in the file LICENCE(GPL V3) in the root of the source
|
||||
* code directory.
|
||||
**************************************************************************************************/
|
||||
#include "xToolsModbusStudioUi.h"
|
||||
#include "xToolsUi.h"
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
const QString appName = QObject::tr("Modbus Studio");
|
||||
return xToolsExec<xToolsModbusStudioUi>(argc, argv, appName);
|
||||
}
|
||||
@ -1,363 +0,0 @@
|
||||
/***************************************************************************************************
|
||||
* Copyright 2023-2024 x-tools-author(x-tools@outlook.com). All rights reserved.
|
||||
*
|
||||
* The file is encoded using "utf8 with bom", it is a part of xTools project.
|
||||
*
|
||||
* xTools is licensed according to the terms in the file LICENCE(GPL V3) in the root of the source
|
||||
* code directory.
|
||||
**************************************************************************************************/
|
||||
#include "xToolsBleCentralTool.h"
|
||||
|
||||
#include <QBluetoothDeviceInfo>
|
||||
#include <QMetaObject>
|
||||
|
||||
#define BLE_ERR_SIG QLowEnergyController::Error
|
||||
|
||||
xToolsBleCentralTool::xToolsBleCentralTool(QObject *parent)
|
||||
: xToolsCommunicationTool(parent)
|
||||
{}
|
||||
|
||||
xToolsBleCentralTool::~xToolsBleCentralTool() {}
|
||||
|
||||
QString xToolsBleCentralTool::serviceName(QVariant service)
|
||||
{
|
||||
QObject *obj = service.value<QObject *>();
|
||||
auto cookedService = qobject_cast<QLowEnergyService *>(obj);
|
||||
if (cookedService) {
|
||||
return cookedService->serviceName();
|
||||
} else {
|
||||
qWarning() << "invalid valud of service, not a object!";
|
||||
}
|
||||
|
||||
return "Invalid";
|
||||
}
|
||||
|
||||
QVariantList xToolsBleCentralTool::characteristics(QVariant service)
|
||||
{
|
||||
QVariantList list;
|
||||
if (service.canConvert<QLowEnergyService *>()) {
|
||||
return list;
|
||||
}
|
||||
auto cookedService = service.value<QLowEnergyService *>();
|
||||
if (cookedService) {
|
||||
auto characteristics = cookedService->characteristics();
|
||||
for (auto &characteristic : characteristics) {
|
||||
list.append(QVariant::fromValue(characteristic));
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
QString xToolsBleCentralTool::characteristicName(QVariant characteristic)
|
||||
{
|
||||
if (characteristic.canConvert<QLowEnergyCharacteristic>()) {
|
||||
auto c = characteristic.value<QLowEnergyCharacteristic>();
|
||||
return c.name();
|
||||
}
|
||||
|
||||
return "Invalid";
|
||||
}
|
||||
|
||||
void xToolsBleCentralTool::readCharacteristic()
|
||||
{
|
||||
if (!(m_serviceIndex >= 0 && m_serviceIndex < m_services.length())) {
|
||||
qWarning() << "invalid service index";
|
||||
return;
|
||||
}
|
||||
|
||||
auto service = m_services.at(m_serviceIndex);
|
||||
auto chs = service->characteristics();
|
||||
if (!(m_characteristicIndex >= 0 && m_characteristicIndex < chs.count())) {
|
||||
qWarning() << "invalid characteristic index";
|
||||
return;
|
||||
}
|
||||
|
||||
auto c = chs.at(m_characteristicIndex);
|
||||
service->readCharacteristic(c);
|
||||
}
|
||||
|
||||
void xToolsBleCentralTool::changeNotify()
|
||||
{
|
||||
if (!((m_serviceIndex >= 0) && (m_serviceIndex < m_services.length()))) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto service = m_services.at(m_serviceIndex);
|
||||
auto characteristics = service->characteristics();
|
||||
if (!((m_characteristicIndex >= 0) && (m_characteristicIndex < characteristics.length()))) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto characteristic = characteristics.at(m_characteristicIndex);
|
||||
auto descriptors = characteristic.descriptors();
|
||||
typedef QBluetoothUuid::DescriptorType SAKDescriptorType;
|
||||
auto type = SAKDescriptorType::ClientCharacteristicConfiguration;
|
||||
for (auto &descriptor : descriptors) {
|
||||
auto value = descriptor.value();
|
||||
if (descriptor.type() != type) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (value == QByteArray::fromHex("0100")) {
|
||||
QByteArray value = QByteArray::fromHex("0000");
|
||||
service->writeDescriptor(descriptor, value);
|
||||
qWarning() << "disable notify";
|
||||
} else {
|
||||
QByteArray value = QByteArray::fromHex("0100");
|
||||
service->writeDescriptor(descriptor, value);
|
||||
qWarning() << "enable notify";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool xToolsBleCentralTool::hasFlag(QVariant characteristic, int flag)
|
||||
{
|
||||
auto ch = characteristic.value<QLowEnergyCharacteristic>();
|
||||
auto properties = ch.properties();
|
||||
if (properties & flag) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool xToolsBleCentralTool::isNotified(QVariant characteristic)
|
||||
{
|
||||
auto cookedCh = characteristic.value<QLowEnergyCharacteristic>();
|
||||
auto desList = cookedCh.descriptors();
|
||||
bool notified = false;
|
||||
for (auto &des : desList) {
|
||||
if (des.value() == QByteArray::fromHex("0100")) {
|
||||
notified = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return notified;
|
||||
}
|
||||
|
||||
bool xToolsBleCentralTool::initialize(QString &errStr)
|
||||
{
|
||||
if (!m_bluetoothDeviceInfo.isValid()) {
|
||||
errStr = "invalid ble information.";
|
||||
return false;
|
||||
}
|
||||
|
||||
m_services.clear();
|
||||
mBleCentral = QLowEnergyController::createCentral(m_bluetoothDeviceInfo);
|
||||
connect(mBleCentral,
|
||||
&QLowEnergyController::serviceDiscovered,
|
||||
mBleCentral,
|
||||
[=](const QBluetoothUuid &newService) { onServiceDiscovered(newService); });
|
||||
connect(mBleCentral, &QLowEnergyController::discoveryFinished, mBleCentral, [=]() {
|
||||
onServiceDiscoveryFinished();
|
||||
});
|
||||
connect(mBleCentral,
|
||||
&QLowEnergyController::errorOccurred,
|
||||
mBleCentral,
|
||||
[=](QLowEnergyController::Error err) { onBleCentralErrorOccuured(err); });
|
||||
connect(mBleCentral, &QLowEnergyController::connected, mBleCentral, [=]() {
|
||||
onBleCentralConnected();
|
||||
});
|
||||
connect(mBleCentral, &QLowEnergyController::disconnected, mBleCentral, [=]() {
|
||||
onBleCentralDisconnected();
|
||||
});
|
||||
|
||||
mBleCentral->connectToDevice();
|
||||
emit serviceDiscoveryStarted();
|
||||
return true;
|
||||
}
|
||||
|
||||
void xToolsBleCentralTool::readBytes()
|
||||
{
|
||||
if (!((m_serviceIndex >= 0) && (m_serviceIndex < m_services.length()))) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto service = m_services.at(m_serviceIndex);
|
||||
auto characteristics = service->characteristics();
|
||||
auto characteristic = characteristics.at(m_characteristicIndex);
|
||||
service->readCharacteristic(characteristic);
|
||||
}
|
||||
|
||||
void xToolsBleCentralTool::writeBytes(const QByteArray &bytes)
|
||||
{
|
||||
if (!((m_serviceIndex >= 0) && (m_serviceIndex < m_services.length()))) {
|
||||
qWarning() << "invalid parameters.";
|
||||
return;
|
||||
}
|
||||
|
||||
auto service = m_services.at(m_serviceIndex);
|
||||
auto characteristics = service->characteristics();
|
||||
auto characteristic = characteristics.at(m_characteristicIndex);
|
||||
if (m_writeModel == 0) {
|
||||
if (!hasFlag(QVariant::fromValue(characteristic), QLowEnergyCharacteristic::Write)) {
|
||||
QString str = "QLowEnergyService::WriteWithResponse";
|
||||
qWarning() << "unsupported write model: " + str;
|
||||
return;
|
||||
}
|
||||
|
||||
qInfo() << "try to write bytes:" << QString::fromLatin1(bytes.toHex());
|
||||
service->writeCharacteristic(characteristic, bytes);
|
||||
} else {
|
||||
if (!hasFlag(QVariant::fromValue(characteristic),
|
||||
QLowEnergyCharacteristic::WriteNoResponse)) {
|
||||
QString str = "QLowEnergyService::WriteWithoutResponse";
|
||||
qWarning() << "unsupported write model: " + str;
|
||||
return;
|
||||
}
|
||||
|
||||
qInfo() << "try to write bytes without response:"
|
||||
<< QString::fromLatin1(bytes.toHex());
|
||||
auto opt = QLowEnergyService::WriteWithoutResponse;
|
||||
service->writeCharacteristic(characteristic, bytes, opt);
|
||||
}
|
||||
}
|
||||
|
||||
void xToolsBleCentralTool::uninitialize()
|
||||
{
|
||||
mBleCentral->disconnectFromDevice();
|
||||
mBleCentral->deleteLater();
|
||||
mBleCentral = nullptr;
|
||||
}
|
||||
|
||||
void xToolsBleCentralTool::onServiceDiscovered(const QBluetoothUuid &newService)
|
||||
{
|
||||
qInfo() << "new ble service discovered:" + newService.toString();
|
||||
}
|
||||
|
||||
void xToolsBleCentralTool::onServiceDiscoveryFinished()
|
||||
{
|
||||
qInfo() << "ble service discovery finished.";
|
||||
QList<QBluetoothUuid> uuids = mBleCentral->services();
|
||||
qInfo() << "service count:" + QString::number(uuids.length());
|
||||
|
||||
for (auto &uuid : uuids) {
|
||||
auto service = mBleCentral->createServiceObject(uuid);
|
||||
if (!service) {
|
||||
continue;
|
||||
}
|
||||
|
||||
connect(service,
|
||||
&QLowEnergyService::characteristicChanged,
|
||||
service,
|
||||
[=](const QLowEnergyCharacteristic &info, const QByteArray &value) {
|
||||
emit outputBytes(value);
|
||||
emit bytesRead(value, info.name());
|
||||
});
|
||||
connect(service,
|
||||
&QLowEnergyService::characteristicRead,
|
||||
service,
|
||||
[=](const QLowEnergyCharacteristic &info, const QByteArray &value) {
|
||||
emit outputBytes(value);
|
||||
emit bytesRead(value, info.name());
|
||||
});
|
||||
connect(service,
|
||||
&QLowEnergyService::characteristicWritten,
|
||||
service,
|
||||
[=](const QLowEnergyCharacteristic &info, const QByteArray &value) {
|
||||
emit bytesWritten(value, info.name());
|
||||
});
|
||||
connect(service,
|
||||
&QLowEnergyService::stateChanged,
|
||||
service,
|
||||
[=](QLowEnergyService::ServiceState newState) {
|
||||
onServiceObjectStateChanged(service, newState);
|
||||
});
|
||||
connect(service,
|
||||
&QLowEnergyService::descriptorWritten,
|
||||
this,
|
||||
&xToolsBleCentralTool::descriptorWritten);
|
||||
|
||||
m_services.append(service);
|
||||
service->discoverDetails();
|
||||
}
|
||||
|
||||
emit serviceDiscoveryFinished();
|
||||
}
|
||||
|
||||
void xToolsBleCentralTool::onBleCentralErrorOccuured(QLowEnergyController::Error err)
|
||||
{
|
||||
if (err == QLowEnergyController::UnknownError) {
|
||||
return;
|
||||
}
|
||||
|
||||
qWarning() << "new ble service error:" + mBleCentral->errorString();
|
||||
exit();
|
||||
}
|
||||
|
||||
void xToolsBleCentralTool::onBleCentralConnected()
|
||||
{
|
||||
qWarning() << "connect to device successfully.";
|
||||
mBleCentral->discoverServices();
|
||||
}
|
||||
|
||||
void xToolsBleCentralTool::onBleCentralDisconnected()
|
||||
{
|
||||
QString msg = "disconnect from device";
|
||||
qWarning() << msg;
|
||||
emit errorOccurred(msg);
|
||||
}
|
||||
|
||||
void xToolsBleCentralTool::onServiceObjectStateChanged(QLowEnergyService *service,
|
||||
QLowEnergyService::ServiceState newState)
|
||||
{
|
||||
Q_UNUSED(service);
|
||||
auto state = QLowEnergyService::RemoteServiceDiscovered;
|
||||
if (newState == state) {
|
||||
qInfo() << "Remote service discovered:" << newState;
|
||||
}
|
||||
}
|
||||
|
||||
QVariant xToolsBleCentralTool::info()
|
||||
{
|
||||
return QVariant::fromValue(m_bluetoothDeviceInfo);
|
||||
}
|
||||
|
||||
void xToolsBleCentralTool::setInfo(QVariant info)
|
||||
{
|
||||
m_bluetoothDeviceInfo = info.value<QBluetoothDeviceInfo>();
|
||||
emit infoChanged();
|
||||
}
|
||||
|
||||
QVariantList xToolsBleCentralTool::services()
|
||||
{
|
||||
QVariantList varList;
|
||||
for (auto &var : m_services) {
|
||||
varList.append(QVariant::fromValue(var));
|
||||
}
|
||||
return varList;
|
||||
}
|
||||
|
||||
int xToolsBleCentralTool::serviceIndex()
|
||||
{
|
||||
return m_serviceIndex;
|
||||
}
|
||||
|
||||
void xToolsBleCentralTool::setServiceIndex(int index)
|
||||
{
|
||||
m_serviceIndex = index;
|
||||
emit serviceIndexChanged();
|
||||
}
|
||||
|
||||
int xToolsBleCentralTool::characteristicIndex()
|
||||
{
|
||||
return m_characteristicIndex;
|
||||
}
|
||||
|
||||
void xToolsBleCentralTool::setCharacteristicIndex(int index)
|
||||
{
|
||||
m_characteristicIndex = index;
|
||||
emit characteristicIndexChanged();
|
||||
}
|
||||
|
||||
int xToolsBleCentralTool::writeModel()
|
||||
{
|
||||
return m_writeModel;
|
||||
}
|
||||
|
||||
void xToolsBleCentralTool::setWriteModel(int model)
|
||||
{
|
||||
m_writeModel = model;
|
||||
emit writeModelChanged();
|
||||
}
|
||||
@ -1,90 +0,0 @@
|
||||
/***************************************************************************************************
|
||||
* Copyright 2023-2024 x-tools-author(x-tools@outlook.com). All rights reserved.
|
||||
*
|
||||
* The file is encoded using "utf8 with bom", it is a part of xTools project.
|
||||
*
|
||||
* xTools is licensed according to the terms in the file LICENCE(GPL V3) in the root of the source
|
||||
* code directory.
|
||||
**************************************************************************************************/
|
||||
#pragma once
|
||||
|
||||
#include <QBluetoothDeviceInfo>
|
||||
#include <QBluetoothUuid>
|
||||
#include <QLowEnergyController>
|
||||
#include <QLowEnergyService>
|
||||
#include <QVariantList>
|
||||
|
||||
#include "xToolsCommunicationTool.h"
|
||||
|
||||
class xToolsBleCentralTool : public xToolsCommunicationTool
|
||||
{
|
||||
Q_OBJECT
|
||||
// clang-format off
|
||||
Q_PROPERTY(QVariant info READ info WRITE setInfo NOTIFY infoChanged)
|
||||
Q_PROPERTY(QVariantList services READ services NOTIFY servicesChanged)
|
||||
Q_PROPERTY(int serviceIndex READ serviceIndex WRITE setServiceIndex NOTIFY serviceIndexChanged)
|
||||
Q_PROPERTY(int characteristicIndex READ characteristicIndex WRITE setCharacteristicIndex NOTIFY characteristicIndexChanged)
|
||||
Q_PROPERTY(int writeModel READ writeModel WRITE setWriteModel NOTIFY writeModelChanged)
|
||||
// clang-format on
|
||||
public:
|
||||
xToolsBleCentralTool(QObject *parent = nullptr);
|
||||
~xToolsBleCentralTool();
|
||||
|
||||
public:
|
||||
Q_INVOKABLE QString serviceName(QVariant service);
|
||||
Q_INVOKABLE QVariantList characteristics(QVariant service);
|
||||
Q_INVOKABLE QString characteristicName(QVariant characteristic);
|
||||
Q_INVOKABLE void readCharacteristic();
|
||||
Q_INVOKABLE void changeNotify();
|
||||
Q_INVOKABLE bool hasFlag(QVariant characteristic, int flag);
|
||||
Q_INVOKABLE bool isNotified(QVariant characteristic);
|
||||
|
||||
signals:
|
||||
void descriptorWritten(const QLowEnergyDescriptor &descriptor, const QByteArray &newValue);
|
||||
void serviceDiscoveryStarted();
|
||||
void serviceDiscoveryFinished();
|
||||
|
||||
protected:
|
||||
bool initialize(QString &errStr) override;
|
||||
void writeBytes(const QByteArray &bytes) override;
|
||||
void readBytes();
|
||||
void uninitialize() override;
|
||||
|
||||
private:
|
||||
QLowEnergyController *mBleCentral{nullptr};
|
||||
|
||||
private:
|
||||
void onServiceDiscovered(const QBluetoothUuid &newService);
|
||||
void onServiceDiscoveryFinished();
|
||||
void onBleCentralErrorOccuured(QLowEnergyController::Error err);
|
||||
void onBleCentralConnected();
|
||||
void onBleCentralDisconnected();
|
||||
void onServiceObjectStateChanged(QLowEnergyService *service,
|
||||
QLowEnergyService::ServiceState newState);
|
||||
|
||||
public:
|
||||
Q_INVOKABLE QVariant info();
|
||||
Q_INVOKABLE void setInfo(QVariant info);
|
||||
Q_INVOKABLE QVariantList services();
|
||||
Q_INVOKABLE int serviceIndex();
|
||||
Q_INVOKABLE void setServiceIndex(int index);
|
||||
Q_INVOKABLE int characteristicIndex();
|
||||
Q_INVOKABLE void setCharacteristicIndex(int index);
|
||||
Q_INVOKABLE int writeModel();
|
||||
Q_INVOKABLE void setWriteModel(int model);
|
||||
|
||||
signals:
|
||||
void infoChanged();
|
||||
void servicesChanged();
|
||||
void serviceIndexChanged();
|
||||
void characteristicsChanged();
|
||||
void characteristicIndexChanged();
|
||||
void writeModelChanged();
|
||||
|
||||
private:
|
||||
QBluetoothDeviceInfo m_bluetoothDeviceInfo;
|
||||
QVector<QLowEnergyService *> m_services;
|
||||
int m_serviceIndex{-1};
|
||||
int m_characteristicIndex{-1};
|
||||
int m_writeModel;
|
||||
};
|
||||
@ -1,269 +0,0 @@
|
||||
/***************************************************************************************************
|
||||
* Copyright 2023-2024 x-tools-author(x-tools@outlook.com). All rights reserved.
|
||||
*
|
||||
* The file is encoded using "utf8 with bom", it is a part of xTools project.
|
||||
*
|
||||
* xTools is licensed according to the terms in the file LICENCE(GPL V3) in the root of the source
|
||||
* code directory.
|
||||
**************************************************************************************************/
|
||||
#include "xToolsBleCentralToolUi.h"
|
||||
#include "ui_xToolsBleCentralToolUi.h"
|
||||
|
||||
#include <QGridLayout>
|
||||
#include <QLabel>
|
||||
#include <QLowEnergyCharacteristic>
|
||||
#include <QMenu>
|
||||
#include <QWidget>
|
||||
#include <QWidgetAction>
|
||||
|
||||
#include "xToolsLineEdit.h"
|
||||
#include "xToolsSpinBox.h"
|
||||
|
||||
xToolsBleCentralToolUi::xToolsBleCentralToolUi(QWidget* parent)
|
||||
: xToolsCommunicationToolUi{parent}
|
||||
, ui(new Ui::xToolsBleCentralToolUi)
|
||||
, mBleTool(Q_NULLPTR)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
ui->progressBar->hide();
|
||||
connect(ui->pushButtonScan,
|
||||
&QPushButton::clicked,
|
||||
this,
|
||||
&xToolsBleCentralToolUi::onPushButtonScanClicked);
|
||||
connect(ui->comboBoxDevices,
|
||||
static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged),
|
||||
this,
|
||||
&xToolsBleCentralToolUi::onComboBoxDevicesActived);
|
||||
connect(ui->comboBoxServices,
|
||||
static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged),
|
||||
this,
|
||||
&xToolsBleCentralToolUi::onComboBoxServicesCurrentIndexChanged);
|
||||
connect(ui->comboBoxCharacteristics,
|
||||
static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged),
|
||||
this,
|
||||
&xToolsBleCentralToolUi::onComboBoxCharacteristicsActived);
|
||||
connect(ui->comboBoxWriteWay,
|
||||
static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged),
|
||||
this,
|
||||
&xToolsBleCentralToolUi::onComboBoxWriteWayCurrentIndexChanged);
|
||||
connect(ui->pushButtonNotify,
|
||||
&QPushButton::clicked,
|
||||
this,
|
||||
&xToolsBleCentralToolUi::onPushButtonNotifyClicked);
|
||||
connect(ui->pushButtonRead,
|
||||
&QPushButton::clicked,
|
||||
this,
|
||||
&xToolsBleCentralToolUi::onPushButtonReadClicked);
|
||||
connect(ui->comboBoxDevices, &xToolsBleDeviceInfoComboBox::finished, this, [=]() {
|
||||
ui->pushButtonScan->setText(tr("Scan"));
|
||||
ui->pushButtonScan->setEnabled(true);
|
||||
});
|
||||
connect(ui->comboBoxDevices, &xToolsBleDeviceInfoComboBox::started, this, [=]() {
|
||||
ui->pushButtonScan->setText(tr("Stop"));
|
||||
ui->pushButtonScan->setEnabled(true);
|
||||
});
|
||||
|
||||
ui->labelWriteWay->setVisible(false);
|
||||
ui->comboBoxWriteWay->setVisible(false);
|
||||
ui->pushButtonNotify->setVisible(false);
|
||||
ui->pushButtonRead->setVisible(false);
|
||||
ui->labelUnsupported->setVisible(false);
|
||||
ui->labelUnsupported->setStyleSheet("QLabel{color:red}");
|
||||
}
|
||||
|
||||
xToolsBleCentralToolUi::~xToolsBleCentralToolUi()
|
||||
{
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void xToolsBleCentralToolUi::onBaseToolUiInitialized(xToolsBaseTool* tool,
|
||||
const QString& settingsGroup)
|
||||
{
|
||||
xToolsCommunicationToolUi::onBaseToolUiInitialized(tool, settingsGroup);
|
||||
|
||||
mBleTool = qobject_cast<xToolsBleCentralTool*>(mTool);
|
||||
if (!mBleTool) {
|
||||
QByteArray msg("invalid SAKBleCentralTool tool");
|
||||
qWarning() << QString::fromLatin1(msg);
|
||||
Q_ASSERT_X(false, __FUNCTION__, msg.data());
|
||||
return;
|
||||
}
|
||||
|
||||
onComboBoxWriteWayCurrentIndexChanged();
|
||||
connect(mBleTool,
|
||||
&xToolsBleCentralTool::descriptorWritten,
|
||||
this,
|
||||
&xToolsBleCentralToolUi::onDescriptorWritten);
|
||||
|
||||
initSettingsMenu(settingsGroup);
|
||||
}
|
||||
|
||||
void xToolsBleCentralToolUi::onIsWorkingChanged(bool isWorking)
|
||||
{
|
||||
if (!isWorking) {
|
||||
ui->progressBar->hide();
|
||||
}
|
||||
}
|
||||
|
||||
void xToolsBleCentralToolUi::initSettingsMenu(const QString& settingsGroup)
|
||||
{
|
||||
QWidget* w = new QWidget(this);
|
||||
QGridLayout* gl = new QGridLayout();
|
||||
w->setLayout(gl);
|
||||
|
||||
int rowIndex = 0;
|
||||
gl->addWidget(new QLabel(tr("Timeout interval(S)"), w), rowIndex, 0, 1, 1);
|
||||
xToolsSpinBox* sp = new xToolsSpinBox(w);
|
||||
sp->setMinimum(10);
|
||||
sp->setMaximum(120);
|
||||
sp->setValue(120);
|
||||
sp->setGroupKey(settingsGroup, "timeoutInterval");
|
||||
gl->addWidget(sp, rowIndex, 1, 1, 1);
|
||||
connect(sp, QOverload<int>::of(&QSpinBox::valueChanged), this, [=](int v) {
|
||||
ui->comboBoxDevices->setTimeoutInterval(v);
|
||||
});
|
||||
|
||||
rowIndex += 1;
|
||||
gl->addWidget(new QLabel(tr("Name filtter"), w), rowIndex, 0, 1, 1);
|
||||
xToolsLineEdit* le = new xToolsLineEdit(w);
|
||||
le->setGroupKey(settingsGroup, "nameFiltter");
|
||||
gl->addWidget(le, rowIndex, 1, 1, 1);
|
||||
connect(le, &xToolsLineEdit::textChanged, this, [=](const QString& text) {
|
||||
ui->comboBoxDevices->setNameFiltter(text);
|
||||
});
|
||||
|
||||
rowIndex += 1;
|
||||
QMenu* menu = new QMenu(this);
|
||||
QPushButton* bt = new QPushButton(tr("OK"));
|
||||
connect(bt, &QPushButton::clicked, menu, &QMenu::close);
|
||||
gl->addWidget(bt, rowIndex, 1, 1, 1);
|
||||
|
||||
QWidgetAction* a = new QWidgetAction(this);
|
||||
a->setDefaultWidget(w);
|
||||
|
||||
menu->addAction(a);
|
||||
ui->pushButtonSettings->setMenu(menu);
|
||||
|
||||
connect(mBleTool,
|
||||
&xToolsBleCentralTool::serviceDiscoveryStarted,
|
||||
this,
|
||||
&xToolsBleCentralToolUi::onServiceDiscoveryStarted);
|
||||
connect(mBleTool,
|
||||
&xToolsBleCentralTool::serviceDiscoveryFinished,
|
||||
this,
|
||||
&xToolsBleCentralToolUi::onServiceDiscoveryFinished);
|
||||
|
||||
int timeoutInterval = sp->value();
|
||||
QString nameFiltter = le->text().trimmed();
|
||||
ui->comboBoxDevices->setTimeoutInterval(timeoutInterval);
|
||||
ui->comboBoxDevices->setNameFiltter(nameFiltter);
|
||||
|
||||
onComboBoxDevicesActived();
|
||||
}
|
||||
|
||||
void xToolsBleCentralToolUi::onServiceDiscoveryStarted()
|
||||
{
|
||||
ui->progressBar->show();
|
||||
}
|
||||
|
||||
void xToolsBleCentralToolUi::onServiceDiscoveryFinished()
|
||||
{
|
||||
ui->comboBoxServices->clear();
|
||||
auto services = mBleTool->services();
|
||||
for (auto& service : services) {
|
||||
auto cookedSerivce = service.value<QLowEnergyService*>();
|
||||
ui->comboBoxServices->addItem(cookedSerivce->serviceName(), service);
|
||||
connect(cookedSerivce,
|
||||
&QLowEnergyService::stateChanged,
|
||||
this,
|
||||
[=](QLowEnergyService::ServiceState state) {
|
||||
if (state == QLowEnergyService::RemoteServiceDiscovered) {
|
||||
onComboBoxServicesCurrentIndexChanged();
|
||||
}
|
||||
});
|
||||
}
|
||||
ui->progressBar->hide();
|
||||
}
|
||||
|
||||
void xToolsBleCentralToolUi::onDescriptorWritten(const QLowEnergyDescriptor& descriptor,
|
||||
const QByteArray& newValue)
|
||||
{
|
||||
Q_UNUSED(descriptor)
|
||||
Q_UNUSED(newValue)
|
||||
onComboBoxCharacteristicsActived();
|
||||
}
|
||||
|
||||
void xToolsBleCentralToolUi::onPushButtonScanClicked()
|
||||
{
|
||||
ui->pushButtonScan->setEnabled(false);
|
||||
if (ui->comboBoxDevices->isActive()) {
|
||||
ui->comboBoxDevices->stopDiscover();
|
||||
} else {
|
||||
ui->comboBoxDevices->startDiscover();
|
||||
}
|
||||
}
|
||||
|
||||
void xToolsBleCentralToolUi::onComboBoxDevicesActived()
|
||||
{
|
||||
QVariant data = ui->comboBoxDevices->currentData();
|
||||
mBleTool->setInfo(data);
|
||||
}
|
||||
|
||||
void xToolsBleCentralToolUi::onComboBoxServicesCurrentIndexChanged()
|
||||
{
|
||||
mBleTool->setServiceIndex(ui->comboBoxServices->currentIndex());
|
||||
auto service = ui->comboBoxServices->currentData();
|
||||
auto cookedSerivce = service.value<QLowEnergyService*>();
|
||||
auto chs = cookedSerivce->characteristics();
|
||||
ui->comboBoxCharacteristics->clear();
|
||||
for (int i = 0; i < chs.count(); i++) {
|
||||
auto ch = chs.at(i);
|
||||
QVariant var = QVariant::fromValue<QLowEnergyCharacteristic>(ch);
|
||||
QString name = ch.name();
|
||||
name = name.isEmpty() ? tr("Characteristics%1").arg(i + 1) : name;
|
||||
ui->comboBoxCharacteristics->addItem(name, var);
|
||||
}
|
||||
}
|
||||
|
||||
void xToolsBleCentralToolUi::onComboBoxCharacteristicsActived()
|
||||
{
|
||||
int index = ui->comboBoxCharacteristics->currentIndex();
|
||||
mBleTool->setCharacteristicIndex(index);
|
||||
|
||||
QVariant ch = ui->comboBoxCharacteristics->currentData();
|
||||
bool writeFlag = mBleTool->hasFlag(ch, QLowEnergyCharacteristic::Write);
|
||||
int writeNoResponse = QLowEnergyCharacteristic::WriteNoResponse;
|
||||
bool writeNoResponseFlag = mBleTool->hasFlag(ch, writeNoResponse);
|
||||
ui->labelWriteWay->setVisible(writeFlag);
|
||||
ui->comboBoxWriteWay->setVisible(writeNoResponseFlag);
|
||||
|
||||
bool readFlag = mBleTool->hasFlag(ch, QLowEnergyCharacteristic::Read);
|
||||
bool notifyFlag = mBleTool->hasFlag(ch, QLowEnergyCharacteristic::Notify);
|
||||
ui->pushButtonNotify->setVisible(notifyFlag);
|
||||
ui->pushButtonRead->setVisible(readFlag);
|
||||
bool supported = writeFlag || writeNoResponseFlag || readFlag || notifyFlag;
|
||||
ui->labelUnsupported->setVisible(!supported);
|
||||
|
||||
if (notifyFlag) {
|
||||
bool isNotified = mBleTool->isNotified(ch);
|
||||
QString txt = isNotified ? tr("Disnotify") : tr("Notify");
|
||||
ui->pushButtonNotify->setText(txt);
|
||||
}
|
||||
}
|
||||
|
||||
void xToolsBleCentralToolUi::onComboBoxWriteWayCurrentIndexChanged()
|
||||
{
|
||||
int index = ui->comboBoxWriteWay->currentIndex();
|
||||
mBleTool->setWriteModel(index);
|
||||
qInfo() << "set write model to:" << index;
|
||||
}
|
||||
|
||||
void xToolsBleCentralToolUi::onPushButtonNotifyClicked()
|
||||
{
|
||||
mBleTool->changeNotify();
|
||||
}
|
||||
|
||||
void xToolsBleCentralToolUi::onPushButtonReadClicked()
|
||||
{
|
||||
mBleTool->readCharacteristic();
|
||||
}
|
||||
@ -1,50 +0,0 @@
|
||||
/***************************************************************************************************
|
||||
* Copyright 2023-2024 x-tools-author(x-tools@outlook.com). All rights reserved.
|
||||
*
|
||||
* The file is encoded using "utf8 with bom", it is a part of xTools project.
|
||||
*
|
||||
* xTools is licensed according to the terms in the file LICENCE(GPL V3) in the root of the source
|
||||
* code directory.
|
||||
**************************************************************************************************/
|
||||
#include <QLowEnergyDescriptor>
|
||||
|
||||
#include "xToolsBleCentralTool.h"
|
||||
#include "xToolsCommunicationToolUi.h"
|
||||
|
||||
namespace Ui {
|
||||
class xToolsBleCentralToolUi;
|
||||
}
|
||||
class xToolsBleCentralToolUi : public xToolsCommunicationToolUi
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit xToolsBleCentralToolUi(QWidget *parent = nullptr);
|
||||
~xToolsBleCentralToolUi();
|
||||
|
||||
protected:
|
||||
virtual void onBaseToolUiInitialized(xToolsBaseTool *tool,
|
||||
const QString &settingsGroup) override;
|
||||
|
||||
virtual void onIsWorkingChanged(bool isWorking) final;
|
||||
|
||||
private:
|
||||
Ui::xToolsBleCentralToolUi *ui{nullptr};
|
||||
xToolsBleCentralTool *mBleTool;
|
||||
const QLoggingCategory mLoggingCategory{"sak.blecentraltoolui"};
|
||||
|
||||
private:
|
||||
void initSettingsMenu(const QString &settingsGroup);
|
||||
|
||||
private slots:
|
||||
void onServiceDiscoveryStarted();
|
||||
void onServiceDiscoveryFinished();
|
||||
void onDescriptorWritten(const QLowEnergyDescriptor &descriptor, const QByteArray &newValue);
|
||||
|
||||
void onPushButtonScanClicked();
|
||||
void onComboBoxDevicesActived();
|
||||
void onComboBoxServicesCurrentIndexChanged();
|
||||
void onComboBoxCharacteristicsActived();
|
||||
void onComboBoxWriteWayCurrentIndexChanged();
|
||||
void onPushButtonNotifyClicked();
|
||||
void onPushButtonReadClicked();
|
||||
};
|
||||
@ -1,185 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>xToolsBleCentralToolUi</class>
|
||||
<widget class="QWidget" name="xToolsBleCentralToolUi">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>256</width>
|
||||
<height>256</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Form</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<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>9</number>
|
||||
</property>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Service</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Devices</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="0">
|
||||
<widget class="QLabel" name="labelWriteWay">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Write way</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="xToolsBleDeviceInfoComboBox" name="comboBoxDevices"/>
|
||||
</item>
|
||||
<item row="7" column="0" colspan="2">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QPushButton" name="pushButtonNotify">
|
||||
<property name="text">
|
||||
<string>Notify</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="pushButtonRead">
|
||||
<property name="text">
|
||||
<string>Read</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="2" column="0" colspan="2">
|
||||
<widget class="Line" name="line">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1">
|
||||
<widget class="QComboBox" name="comboBoxCharacteristics"/>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QComboBox" name="comboBoxServices">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="9" column="0" colspan="2">
|
||||
<widget class="QProgressBar" name="progressBar">
|
||||
<property name="maximum">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>-1</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="1">
|
||||
<widget class="QComboBox" name="comboBoxWriteWay">
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>WriteWithResponse</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>WriteWithoutResponse</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Characteristic</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0" colspan="2">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<item>
|
||||
<widget class="QPushButton" name="pushButtonSettings">
|
||||
<property name="text">
|
||||
<string>Settings</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="pushButtonScan">
|
||||
<property name="text">
|
||||
<string>Scan</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="6" column="0" colspan="2">
|
||||
<widget class="QLabel" name="labelUnsupported">
|
||||
<property name="text">
|
||||
<string>(Unsupported characteristic)</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>xToolsBleDeviceInfoComboBox</class>
|
||||
<extends>QComboBox</extends>
|
||||
<header location="global">xToolsBleDeviceInfoComboBox.h</header>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
Loading…
Reference in New Issue
Block a user