diff --git a/Servo/Servo.pro b/Servo/Servo.pro index 3162733..23df4c0 100644 --- a/Servo/Servo.pro +++ b/Servo/Servo.pro @@ -1,5 +1,8 @@ QT -= gui +QT += serialbus +QT += serialport + TEMPLATE = lib DEFINES += SERVO_LIBRARY @@ -18,12 +21,10 @@ DEFINES += QT_DEPRECATED_WARNINGS #DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 SOURCES += \ - $$files(*.cpp, true) \ \ - - + $$files(*.cpp, true) HEADERS += \ - $$files(*.h, true) \ \ + $$files(*.h, true) INCLUDEPATH += $$PWD/include diff --git a/Servo/include/ModbusConfig.h b/Servo/include/ModbusConfig.h new file mode 100644 index 0000000..eab91b1 --- /dev/null +++ b/Servo/include/ModbusConfig.h @@ -0,0 +1,17 @@ +#ifndef SETTINGSERIALPARAMETERS_H +#define SETTINGSERIALPARAMETERS_H + +#include + +struct ModbusConfig { + QString serialPort; + int clientAddress; + int parity = QSerialPort::EvenParity; + int baud = QSerialPort::Baud19200; + int dataBits = QSerialPort::Data8; + int stopBits = QSerialPort::OneStop; + int responseTime = 1000; + int numberOfRetries = 3; +}; + +#endif //SETTINGSERIALPARAMETERS_H diff --git a/Servo/include/ModbusMaster.h b/Servo/include/ModbusMaster.h index cd836ed..732b2f4 100644 --- a/Servo/include/ModbusMaster.h +++ b/Servo/include/ModbusMaster.h @@ -2,16 +2,31 @@ #define MODBUSMASTER_H #include +#include + +#include "ServoException.h" +#include "ModbusConfig.h" + +class QModbusClient; class ModbusMaster : public QObject { Q_OBJECT -public: - explicit ModbusMaster(QObject *parent = nullptr); -signals: +private: + bool _initialized = false; + QModbusClient* _modbusDevice = nullptr; + int _clientAddress; + +public: + explicit ModbusMaster(QObject* parent = nullptr); -public slots: +//uncrustify off +public slots: +//uncrustify on + void init(); + void connectToDevice(ModbusConfig modbusConfig); + void connectionStateChanged(QModbusDevice::State state); }; -#endif // MODBUSMASTER_H +#endif //MODBUSMASTER_H diff --git a/Servo/include/ModbusWrapper.h b/Servo/include/ModbusWrapper.h index c5373ac..8c92459 100644 --- a/Servo/include/ModbusWrapper.h +++ b/Servo/include/ModbusWrapper.h @@ -2,16 +2,32 @@ #define MODBUSWRAPPER_H #include +#include + +#include "ModbusMaster.h" +#include "ModbusConfig.h" class ModbusWrapper : public QObject { Q_OBJECT + +private: + ModbusMaster modbusMaster; + QThread workerThread; + public: - explicit ModbusWrapper(QObject *parent = nullptr); + explicit ModbusWrapper(QObject* parent = nullptr); + ~ModbusWrapper(); + void connectToDevice(ModbusConfig modbusConfig); + void init(); signals: + void connectOrder(ModbusConfig modbusConfig); + void initOrder(); + //uncrustify off public slots: + //uncrustify on }; -#endif // MODBUSWRAPPER_H +#endif //MODBUSWRAPPER_H diff --git a/Servo/include/ServoException.h b/Servo/include/ServoException.h new file mode 100644 index 0000000..f4b10cc --- /dev/null +++ b/Servo/include/ServoException.h @@ -0,0 +1,25 @@ +#ifndef SERVOEXCEPTION_H +#define SERVOEXCEPTION_H + +#include +#include + +class ServoException : public std::exception +{ +private: + QString _str; + +public: + ServoException(QString str) + { + _str = str; + qDebug() << "Error Text is: " << _str; + } + + virtual const char* what() const throw() + { + return _str.toStdString().c_str(); + } +}; + +#endif //SERVOEXCEPTION_H diff --git a/Servo/src/ModbusMaster.cpp b/Servo/src/ModbusMaster.cpp index 705072b..1c315ab 100644 --- a/Servo/src/ModbusMaster.cpp +++ b/Servo/src/ModbusMaster.cpp @@ -1,6 +1,70 @@ -#include "../include/ModbusMaster.h" +#include "ModbusMaster.h" -ModbusMaster::ModbusMaster(QObject *parent) : QObject(parent) +#include + +ModbusMaster::ModbusMaster(QObject* parent) : QObject(parent) +{ +} + +/*************************************************************************************************/ +void ModbusMaster::init() +{ + if(!_initialized) + { + _modbusDevice = nullptr; + _modbusDevice = new QModbusRtuSerialMaster(this); + + connect(_modbusDevice, &QModbusClient::errorOccurred, [this](QModbusDevice::Error) + { + throw ServoException(_modbusDevice->errorString()); + }); + + connect(_modbusDevice, &QModbusDevice::stateChanged, this, + &ModbusMaster::connectionStateChanged); + + _initialized = true; + } + else + { + throw ServoException("Modbus Device Created Before Handle it"); + } + + qDebug() << "internal init"; +} + +/*************************************************************************************************/ +void ModbusMaster::connectToDevice(ModbusConfig modbusConfig) +{ + if(_modbusDevice->state() != QModbusDevice::ConnectedState) + { + _clientAddress = modbusConfig.clientAddress; + _modbusDevice->setConnectionParameter(QModbusDevice::SerialPortNameParameter, + modbusConfig.serialPort); + _modbusDevice->setConnectionParameter(QModbusDevice::SerialParityParameter, + modbusConfig.parity); + _modbusDevice->setConnectionParameter(QModbusDevice::SerialBaudRateParameter, + modbusConfig.baud); + _modbusDevice->setConnectionParameter(QModbusDevice::SerialDataBitsParameter, + modbusConfig.dataBits); + _modbusDevice->setConnectionParameter(QModbusDevice::SerialStopBitsParameter, + modbusConfig.stopBits); + _modbusDevice->setTimeout(modbusConfig.responseTime); + _modbusDevice->setNumberOfRetries(modbusConfig.numberOfRetries); + + if(!_modbusDevice->connectDevice()) + { + throw ServoException(_modbusDevice->errorString()); + } + } +} + +/*************************************************************************************************/ +void ModbusMaster::connectionStateChanged(QModbusDevice::State state) { + if(state == QModbusDevice::UnconnectedState) + { + throw ServoException("Connection wasnt prepared"); + } + qDebug() << "internal connect"; } diff --git a/Servo/src/ModbusWrapper.cpp b/Servo/src/ModbusWrapper.cpp index b835c00..1267781 100644 --- a/Servo/src/ModbusWrapper.cpp +++ b/Servo/src/ModbusWrapper.cpp @@ -1,5 +1,47 @@ #include "ModbusWrapper.h" +#include ModbusWrapper::ModbusWrapper(QObject* parent) : QObject(parent) { } + +/*************************************************************************************************/ +ModbusWrapper::~ModbusWrapper() +{ + workerThread.quit(); + workerThread.wait(); +} + +/*************************************************************************************************/ +void ModbusWrapper::init() +{ + modbusMaster.moveToThread(&workerThread); + workerThread.setObjectName("workerThread"); + workerThread.start(); + + QEventLoop loop; + connect(&workerThread, &QThread::started, &loop, &QEventLoop::quit); + loop.exec(); + + connect(this, + &ModbusWrapper::initOrder, + &modbusMaster, + &ModbusMaster::init, + Qt::BlockingQueuedConnection); + connect(this, + &ModbusWrapper::connectOrder, + &modbusMaster, + &ModbusMaster::connectToDevice, + Qt::BlockingQueuedConnection); + + emit initOrder(); + + qDebug() << "init done"; +} + +/*************************************************************************************************/ +void ModbusWrapper::connectToDevice(ModbusConfig modbusConfig) +{ + emit connectOrder(modbusConfig); + qDebug() << "connect done"; +} diff --git a/ServoApplication.pro b/ServoApplication.pro index 50728cd..cc0f007 100644 --- a/ServoApplication.pro +++ b/ServoApplication.pro @@ -5,3 +5,4 @@ SUBDIRS += \ Test Test.depends += Servo + diff --git a/Test/MainWindow.cpp b/Test/MainWindow.cpp index ec12972..ca1490f 100644 --- a/Test/MainWindow.cpp +++ b/Test/MainWindow.cpp @@ -1,15 +1,37 @@ #include "MainWindow.h" #include "ui_MainWindow.h" -MainWindow::MainWindow(QWidget *parent) +MainWindow::MainWindow(QWidget* parent) : QMainWindow(parent) , ui(new Ui::MainWindow) { ui->setupUi(this); } +/*************************************************************************************************/ MainWindow::~MainWindow() { delete ui; } +/*************************************************************************************************/ +void MainWindow::on_connect_clicked() +{ + try + { + configDevice.serialPort = "/dev/pts/2"; + configDevice.clientAddress = 1; + configDevice.responseTime = 1000; + configDevice.numberOfRetries = 3; + qDebug() << "before init"; + modbusWrapper.init(); + qDebug() << "after init"; + qDebug() << "before connect"; + modbusWrapper.connectToDevice(configDevice); + qDebug() << "after connect"; + } + catch(ServoException ex) + { + qDebug() << ex.what(); + } +} diff --git a/Test/MainWindow.h b/Test/MainWindow.h index 274dd1b..a86b711 100644 --- a/Test/MainWindow.h +++ b/Test/MainWindow.h @@ -3,19 +3,31 @@ #include +#include "ModbusWrapper.h" +#include "ModbusConfig.h" + QT_BEGIN_NAMESPACE -namespace Ui { class MainWindow; } +namespace Ui { class MainWindow; +} QT_END_NAMESPACE class MainWindow : public QMainWindow { Q_OBJECT +private: + Ui::MainWindow* ui; + ModbusWrapper modbusWrapper; + ModbusConfig configDevice; + public: - MainWindow(QWidget *parent = nullptr); + MainWindow(QWidget* parent = nullptr); ~MainWindow(); -private: - Ui::MainWindow *ui; + //uncrustify off +private slots: + void on_connect_clicked(); + //uncrustify on }; -#endif // MAINWINDOW_H + +#endif //MAINWINDOW_H diff --git a/Test/MainWindow.ui b/Test/MainWindow.ui index b232854..594c3eb 100644 --- a/Test/MainWindow.ui +++ b/Test/MainWindow.ui @@ -13,8 +13,31 @@ MainWindow - - + + + + + 420 + 40 + 89 + 25 + + + + Connect + + + + + + + 0 + 0 + 800 + 22 + + + diff --git a/Test/Test.pro b/Test/Test.pro index 7d0737c..fa2dff8 100644 --- a/Test/Test.pro +++ b/Test/Test.pro @@ -2,6 +2,9 @@ QT += core gui greaterThan(QT_MAJOR_VERSION, 4): QT += widgets +QT += serialbus +QT += serialport + CONFIG += c++11 # The following define makes your compiler emit warnings if you use @@ -22,6 +25,8 @@ SOURCES += \ HEADERS += \ MainWindow.h +INCLUDEPATH += $$PWD/../Servo/include + FORMS += \ MainWindow.ui diff --git a/Test/main.cpp b/Test/main.cpp index 723a9ab..730adc0 100644 --- a/Test/main.cpp +++ b/Test/main.cpp @@ -1,11 +1,37 @@ #include "MainWindow.h" - +#include #include -int main(int argc, char *argv[]) +class MyApplication : public QApplication { - QApplication a(argc, argv); +public: + MyApplication(int& argc, char** argv) : + QApplication(argc, argv) + { + } + + virtual ~MyApplication() + { + } + + //reimplemented from QApplication so we can throw exceptions in slots + virtual bool notify(QObject* receiver, QEvent* event) { + try { + return QApplication::notify(receiver, event); + } + catch(std::exception& e) + { + ; + } + + return false; + } +}; + +int main(int argc, char* argv[]) { + MyApplication app(argc, argv); MainWindow w; w.show(); - return a.exec(); + + return app.exec(); }