diff options
author | Karsten Heimrich <karsten.heimrich@theqtcompany.com> | 2015-12-20 23:28:00 +0100 |
---|---|---|
committer | Alex Blasche <alexander.blasche@theqtcompany.com> | 2015-12-21 08:13:45 +0000 |
commit | f6fb18d1b1f348bb84b3212dd22f08332b854186 (patch) | |
tree | 327adc327e3ed121a3fdde74bb0fdeda38a631b0 | |
parent | 5319702278cb1afe00687bda29f6791d3c56117e (diff) |
Editor to send handcrafted ADU's.
Change-Id: Ia4685e4ba8df55f89f17c6f3c7e8a0b2c30a3ca4
Reviewed-by: Alex Blasche <alexander.blasche@theqtcompany.com>
-rw-r--r-- | examples/serialbus/modbus/adueditor/adueditor.pro | 10 | ||||
-rw-r--r-- | examples/serialbus/modbus/adueditor/interface.ui | 1951 | ||||
-rw-r--r-- | examples/serialbus/modbus/adueditor/main.cpp | 55 | ||||
-rw-r--r-- | examples/serialbus/modbus/adueditor/mainwindow.cpp | 216 | ||||
-rw-r--r-- | examples/serialbus/modbus/adueditor/mainwindow.h | 94 | ||||
-rw-r--r-- | examples/serialbus/modbus/adueditor/modbustcpclient.cpp | 68 | ||||
-rw-r--r-- | examples/serialbus/modbus/adueditor/modbustcpclient.h | 65 | ||||
-rw-r--r-- | examples/serialbus/modbus/adueditor/modbustcpclient_p.h | 122 | ||||
-rw-r--r-- | examples/serialbus/modbus/adueditor/plaintextedit.h | 83 | ||||
-rw-r--r-- | examples/serialbus/modbus/modbus.pro | 3 | ||||
-rw-r--r-- | src/serialbus/qmodbustcpclient_p.h | 5 |
11 files changed, 2668 insertions, 4 deletions
diff --git a/examples/serialbus/modbus/adueditor/adueditor.pro b/examples/serialbus/modbus/adueditor/adueditor.pro new file mode 100644 index 0000000..7463d71 --- /dev/null +++ b/examples/serialbus/modbus/adueditor/adueditor.pro @@ -0,0 +1,10 @@ +TEMPLATE = app +CONFIG += c++11 +INCLUDEPATH += . +TARGET = adueditor +QT += serialbus serialport widgets +QT += serialbus-private core-private + +FORMS += interface.ui +SOURCES += main.cpp mainwindow.cpp modbustcpclient.cpp +HEADERS += mainwindow.h plaintextedit.h modbustcpclient.h modbustcpclient_p.h diff --git a/examples/serialbus/modbus/adueditor/interface.ui b/examples/serialbus/modbus/adueditor/interface.ui new file mode 100644 index 0000000..9d904b8 --- /dev/null +++ b/examples/serialbus/modbus/adueditor/interface.ui @@ -0,0 +1,1951 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>MainWindow</class> + <widget class="QMainWindow" name="MainWindow"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>667</width> + <height>465</height> + </rect> + </property> + <property name="windowTitle"> + <string>Modbus ADU Editor</string> + </property> + <property name="unifiedTitleAndToolBarOnMac"> + <bool>false</bool> + </property> + <widget class="QWidget" name="centralwidget"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <layout class="QGridLayout" name="gridLayout_4" rowstretch="0,0,0,1" columnstretch="0,1"> + <item row="0" column="0" rowspan="2"> + <widget class="QGroupBox" name="settingsBox"> + <property name="title"> + <string/> + </property> + <layout class="QGridLayout" name="gridLayout_2"> + <item row="1" 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="2" column="0"> + <spacer name="horizontalSpacer_4"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeType"> + <enum>QSizePolicy::Maximum</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>20</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item row="2" column="1"> + <widget class="QPushButton" name="connectButton"> + <property name="text"> + <string>Connect</string> + </property> + <property name="checkable"> + <bool>false</bool> + </property> + <property name="checked"> + <bool>false</bool> + </property> + </widget> + </item> + <item row="0" column="0" colspan="3"> + <widget class="QWidget" name="settingsWidget" native="true"> + <layout class="QHBoxLayout" name="horizontalLayout"> + <property name="leftMargin"> + <number>0</number> + </property> + <property name="topMargin"> + <number>0</number> + </property> + <property name="rightMargin"> + <number>0</number> + </property> + <property name="bottomMargin"> + <number>0</number> + </property> + <item> + <layout class="QGridLayout" name="gridLayout"> + <item row="7" column="0"> + <spacer name="horizontalSpacer"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeType"> + <enum>QSizePolicy::Maximum</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>13</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item row="11" column="0" colspan="2"> + <widget class="QLabel" name="timeoutLabel"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string>Timeout (msec):</string> + </property> + <property name="alignment"> + <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set> + </property> + <property name="buddy"> + <cstring>timeoutSpin</cstring> + </property> + </widget> + </item> + <item row="7" column="1"> + <widget class="QLabel" name="tcpPortLabel"> + <property name="enabled"> + <bool>false</bool> + </property> + <property name="sizePolicy"> + <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string>Port:</string> + </property> + <property name="alignment"> + <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set> + </property> + <property name="buddy"> + <cstring>tcpPortEdit</cstring> + </property> + </widget> + </item> + <item row="1" column="0"> + <spacer name="horizontalSpacer_3"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeType"> + <enum>QSizePolicy::Maximum</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>13</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item row="8" column="2"> + <widget class="QLineEdit" name="tcpAddressEdit"> + <property name="enabled"> + <bool>false</bool> + </property> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>0</width> + <height>0</height> + </size> + </property> + <property name="text"> + <string>127.0.0.1</string> + </property> + </widget> + </item> + <item row="9" column="0" colspan="3"> + <widget class="Line" name="line"> + <property name="minimumSize"> + <size> + <width>0</width> + <height>0</height> + </size> + </property> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + </widget> + </item> + <item row="8" column="1"> + <widget class="QLabel" name="tcpAddressLabel"> + <property name="enabled"> + <bool>false</bool> + </property> + <property name="sizePolicy"> + <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string>Address:</string> + </property> + <property name="alignment"> + <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set> + </property> + <property name="buddy"> + <cstring>tcpAddressEdit</cstring> + </property> + </widget> + </item> + <item row="1" column="2"> + <widget class="QComboBox" name="serialPortCombo"/> + </item> + <item row="8" column="0"> + <spacer name="horizontalSpacer_2"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeType"> + <enum>QSizePolicy::Maximum</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>13</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item row="7" column="2"> + <widget class="QLineEdit" name="tcpPortEdit"> + <property name="enabled"> + <bool>false</bool> + </property> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>0</width> + <height>0</height> + </size> + </property> + <property name="text"> + <string>502</string> + </property> + </widget> + </item> + <item row="1" column="1"> + <widget class="QLabel" name="serialPortLabel"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string>Port:</string> + </property> + <property name="alignment"> + <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set> + </property> + <property name="buddy"> + <cstring>serialPortCombo</cstring> + </property> + </widget> + </item> + <item row="11" column="2"> + <widget class="QSpinBox" name="timeoutSpin"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>0</width> + <height>0</height> + </size> + </property> + <property name="minimum"> + <number>50</number> + </property> + <property name="maximum"> + <number>100000</number> + </property> + <property name="value"> + <number>1000</number> + </property> + </widget> + </item> + <item row="0" column="0" colspan="2"> + <widget class="QRadioButton" name="serialRadio"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Maximum" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string>Serial</string> + </property> + <property name="checked"> + <bool>true</bool> + </property> + </widget> + </item> + <item row="10" column="0" colspan="2"> + <widget class="QLabel" name="retriesLabel"> + <property name="enabled"> + <bool>true</bool> + </property> + <property name="sizePolicy"> + <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string>Number of retries:</string> + </property> + <property name="alignment"> + <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set> + </property> + <property name="buddy"> + <cstring>retriesSpin</cstring> + </property> + </widget> + </item> + <item row="6" column="0" colspan="2"> + <widget class="QRadioButton" name="tcpRadio"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Maximum" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string>TCP</string> + </property> + </widget> + </item> + <item row="10" column="2"> + <widget class="QSpinBox" name="retriesSpin"> + <property name="enabled"> + <bool>true</bool> + </property> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>0</width> + <height>0</height> + </size> + </property> + <property name="value"> + <number>3</number> + </property> + </widget> + </item> + <item row="2" column="1"> + <widget class="QLabel" name="parityLabel"> + <property name="text"> + <string>Parity:</string> + </property> + <property name="buddy"> + <cstring>parityCombo</cstring> + </property> + </widget> + </item> + <item row="3" column="1"> + <widget class="QLabel" name="dataBitsLabel"> + <property name="text"> + <string>Data Bits:</string> + </property> + <property name="buddy"> + <cstring>dataBitsCombo</cstring> + </property> + </widget> + </item> + <item row="4" column="1"> + <widget class="QLabel" name="stopBitsLabel"> + <property name="text"> + <string>Stop Bits:</string> + </property> + <property name="buddy"> + <cstring>stopBitsCombo</cstring> + </property> + </widget> + </item> + <item row="5" column="1"> + <widget class="QLabel" name="baudRateLabel"> + <property name="text"> + <string>BaudRate:</string> + </property> + <property name="buddy"> + <cstring>baudRateCombo</cstring> + </property> + </widget> + </item> + <item row="2" column="2"> + <widget class="QComboBox" name="parityCombo"> + <property name="currentIndex"> + <number>1</number> + </property> + <item> + <property name="text"> + <string>No</string> + </property> + </item> + <item> + <property name="text"> + <string>Even</string> + </property> + </item> + <item> + <property name="text"> + <string>Odd</string> + </property> + </item> + <item> + <property name="text"> + <string>Space</string> + </property> + </item> + <item> + <property name="text"> + <string>Mark</string> + </property> + </item> + </widget> + </item> + <item row="3" column="2"> + <widget class="QComboBox" name="dataBitsCombo"> + <property name="currentIndex"> + <number>3</number> + </property> + <item> + <property name="text"> + <string>5</string> + </property> + </item> + <item> + <property name="text"> + <string>6</string> + </property> + </item> + <item> + <property name="text"> + <string>7</string> + </property> + </item> + <item> + <property name="text"> + <string>8</string> + </property> + </item> + </widget> + </item> + <item row="4" column="2"> + <widget class="QComboBox" name="stopBitsCombo"> + <item> + <property name="text"> + <string>1</string> + </property> + </item> + <item> + <property name="text"> + <string>3</string> + </property> + </item> + <item> + <property name="text"> + <string>2</string> + </property> + </item> + </widget> + </item> + <item row="5" column="2"> + <widget class="QComboBox" name="baudRateCombo"> + <property name="currentIndex"> + <number>4</number> + </property> + <item> + <property name="text"> + <string>1200</string> + </property> + </item> + <item> + <property name="text"> + <string>2400</string> + </property> + </item> + <item> + <property name="text"> + <string>4800</string> + </property> + </item> + <item> + <property name="text"> + <string>9600</string> + </property> + </item> + <item> + <property name="text"> + <string>19200</string> + </property> + </item> + <item> + <property name="text"> + <string>38400</string> + </property> + </item> + <item> + <property name="text"> + <string>57600</string> + </property> + </item> + <item> + <property name="text"> + <string>115200</string> + </property> + </item> + </widget> + </item> + </layout> + </item> + </layout> + </widget> + </item> + <item row="2" column="2"> + <widget class="QPushButton" name="disconnectButton"> + <property name="enabled"> + <bool>false</bool> + </property> + <property name="text"> + <string>Disconnect</string> + </property> + </widget> + </item> + </layout> + </widget> + </item> + <item row="0" column="1"> + <widget class="QStackedWidget" name="stackedWidget"> + <property name="currentIndex"> + <number>0</number> + </property> + <widget class="QWidget" name="page"> + <layout class="QGridLayout" name="gridLayout_8"> + <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"> + <widget class="QGroupBox" name="groupBox"> + <property name="title"> + <string/> + </property> + <layout class="QGridLayout" name="gridLayout_7"> + <item row="0" column="0"> + <widget class="QLabel" name="addressLabel"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string>Server address:</string> + </property> + <property name="alignment"> + <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set> + </property> + <property name="buddy"> + <cstring>addressSpin</cstring> + </property> + </widget> + </item> + <item row="1" column="0"> + <widget class="QLabel" name="fcSerialLabel"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Maximum" vsizetype="Preferred"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string>Function code:</string> + </property> + <property name="buddy"> + <cstring>fcSerialDrop</cstring> + </property> + </widget> + </item> + <item row="1" column="1" colspan="2"> + <widget class="QComboBox" name="fcSerialDrop"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <item> + <property name="text"> + <string>Type your custom function code and data below</string> + </property> + </item> + <item> + <property name="text"> + <string>0x01 - ReadCoils</string> + </property> + </item> + <item> + <property name="text"> + <string>0x02 - Read Discrete Inputs</string> + </property> + </item> + <item> + <property name="text"> + <string>0x03 - Read Holding Registers</string> + </property> + </item> + <item> + <property name="text"> + <string>0x04 - Read Input Registers</string> + </property> + </item> + <item> + <property name="text"> + <string>0x05 - Write Single Coil</string> + </property> + </item> + <item> + <property name="text"> + <string>0x06 - Write Single Register</string> + </property> + </item> + <item> + <property name="text"> + <string>0x07 - Read Exception Status</string> + </property> + </item> + <item> + <property name="text"> + <string>0x08 - Diagnostics</string> + </property> + </item> + <item> + <property name="text"> + <string>0x0B - Get Comm Event Counter</string> + </property> + </item> + <item> + <property name="text"> + <string>0x0C - Get Comm Event Log</string> + </property> + </item> + <item> + <property name="text"> + <string>0x0F - Write Multiple Coils</string> + </property> + </item> + <item> + <property name="text"> + <string>0x10 - Write Multiple Registers</string> + </property> + </item> + <item> + <property name="text"> + <string>0x11 - Report Server Id</string> + </property> + </item> + <item> + <property name="text"> + <string>0x14 - Read File Record</string> + </property> + </item> + <item> + <property name="text"> + <string>0x15 - Write File Record</string> + </property> + </item> + <item> + <property name="text"> + <string>0x16 - Mask Write Register</string> + </property> + </item> + <item> + <property name="text"> + <string>0x17 - Read/Write Multiple Registers</string> + </property> + </item> + <item> + <property name="text"> + <string>0x18 - Read Fifo Queue</string> + </property> + </item> + <item> + <property name="text"> + <string>0x2B - Encapsulated Interface Transport</string> + </property> + </item> + </widget> + </item> + <item row="2" column="0"> + <widget class="QLabel" name="pduSerialLabel"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Maximum" vsizetype="Preferred"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string>Data:</string> + </property> + <property name="buddy"> + <cstring>pduSerialLine</cstring> + </property> + </widget> + </item> + <item row="2" column="1" colspan="2"> + <widget class="QLineEdit" name="pduSerialLine"> + <property name="text"> + <string/> + </property> + <property name="placeholderText"> + <string>Hexadecimal representation of the data in big-endian byte order.</string> + </property> + </widget> + </item> + <item row="3" column="1"> + <spacer name="verticalSpacer_7"> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>20</width> + <height>163</height> + </size> + </property> + </spacer> + </item> + <item row="0" column="1" colspan="2"> + <widget class="QSpinBox" name="addressSpin"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>0</width> + <height>0</height> + </size> + </property> + <property name="specialValueText"> + <string>broadcast</string> + </property> + <property name="maximum"> + <number>255</number> + </property> + <property name="value"> + <number>1</number> + </property> + </widget> + </item> + </layout> + </widget> + </item> + </layout> + </widget> + <widget class="QWidget" name="page_2"> + <layout class="QGridLayout" name="gridLayout_9"> + <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"> + <widget class="QGroupBox" name="groupBox_2"> + <property name="title"> + <string/> + </property> + <layout class="QGridLayout" name="gridLayout_6"> + <item row="0" column="0" colspan="3"> + <layout class="QGridLayout" name="gridLayout_3"> + <item row="0" column="0"> + <layout class="QVBoxLayout" name="verticalLayout_2"> + <item> + <layout class="QHBoxLayout" name="horizontalLayout_7"> + <item> + <widget class="QLabel" name="tiLabel"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Maximum" vsizetype="Preferred"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string>Transaction identifier</string> + </property> + </widget> + </item> + <item> + <widget class="Line" name="tiLine"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + </widget> + </item> + </layout> + </item> + <item> + <layout class="QHBoxLayout" name="horizontalLayout_4"> + <item> + <widget class="QLabel" name="ti1Label"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Maximum" vsizetype="Preferred"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string>1. Byte:</string> + </property> + <property name="buddy"> + <cstring>ti1Spin</cstring> + </property> + </widget> + </item> + <item> + <widget class="QSpinBox" name="ti1Spin"> + <property name="maximum"> + <number>255</number> + </property> + </widget> + </item> + <item> + <widget class="QLabel" name="ti2Label"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Maximum" vsizetype="Preferred"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string>2. Byte:</string> + </property> + <property name="buddy"> + <cstring>ti2Spin</cstring> + </property> + </widget> + </item> + <item> + <widget class="QSpinBox" name="ti2Spin"> + <property name="maximum"> + <number>255</number> + </property> + </widget> + </item> + </layout> + </item> + </layout> + </item> + <item row="0" column="1"> + <spacer name="horizontalSpacer_6"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeType"> + <enum>QSizePolicy::Fixed</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>35</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item row="0" column="2"> + <layout class="QVBoxLayout" name="verticalLayout"> + <item> + <layout class="QHBoxLayout" name="horizontalLayout_6"> + <item> + <widget class="QLabel" name="piLabel"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Maximum" vsizetype="Preferred"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string>Protocol identifier</string> + </property> + </widget> + </item> + <item> + <widget class="Line" name="piLine"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + </widget> + </item> + </layout> + </item> + <item> + <layout class="QHBoxLayout" name="horizontalLayout_5"> + <item> + <widget class="QLabel" name="pi1Label"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Maximum" vsizetype="Preferred"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string>1. Byte:</string> + </property> + <property name="buddy"> + <cstring>pi1Spin</cstring> + </property> + </widget> + </item> + <item> + <widget class="QSpinBox" name="pi1Spin"> + <property name="maximum"> + <number>255</number> + </property> + </widget> + </item> + <item> + <widget class="QLabel" name="pi2Label"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Maximum" vsizetype="Preferred"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string>2. Byte:</string> + </property> + <property name="buddy"> + <cstring>pi2Spin</cstring> + </property> + </widget> + </item> + <item> + <widget class="QSpinBox" name="pi2Spin"> + <property name="maximum"> + <number>255</number> + </property> + </widget> + </item> + </layout> + </item> + </layout> + </item> + <item row="1" column="0"> + <spacer name="verticalSpacer_3"> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + <property name="sizeType"> + <enum>QSizePolicy::Fixed</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>20</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item row="1" column="2"> + <spacer name="verticalSpacer_4"> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + <property name="sizeType"> + <enum>QSizePolicy::Fixed</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>20</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item row="2" column="0"> + <layout class="QVBoxLayout" name="verticalLayout_3"> + <item> + <layout class="QHBoxLayout" name="horizontalLayout_8"> + <item> + <widget class="QLabel" name="lLabel"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Maximum" vsizetype="Preferred"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string>Length</string> + </property> + </widget> + </item> + <item> + <widget class="Line" name="lLine"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + </widget> + </item> + </layout> + </item> + <item> + <layout class="QHBoxLayout" name="horizontalLayout_3"> + <item> + <widget class="QLabel" name="l1Label"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Maximum" vsizetype="Preferred"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string>1. Byte:</string> + </property> + <property name="buddy"> + <cstring>l1Spin</cstring> + </property> + </widget> + </item> + <item> + <widget class="QSpinBox" name="l1Spin"> + <property name="maximum"> + <number>255</number> + </property> + </widget> + </item> + <item> + <widget class="QLabel" name="l2Label"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Maximum" vsizetype="Preferred"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string>2. Byte:</string> + </property> + <property name="buddy"> + <cstring>l2Spin</cstring> + </property> + </widget> + </item> + <item> + <widget class="QSpinBox" name="l2Spin"> + <property name="maximum"> + <number>255</number> + </property> + </widget> + </item> + </layout> + </item> + </layout> + </item> + <item row="2" column="2"> + <layout class="QVBoxLayout" name="verticalLayout_4"> + <item> + <layout class="QHBoxLayout" name="horizontalLayout_9"> + <item> + <widget class="QLabel" name="uiLabel"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Maximum" vsizetype="Preferred"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string>Unit identifier</string> + </property> + </widget> + </item> + <item> + <widget class="Line" name="line_3"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + </widget> + </item> + </layout> + </item> + <item> + <layout class="QHBoxLayout" name="horizontalLayout_10"> + <item> + <widget class="QLabel" name="ui1Label"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Maximum" vsizetype="Preferred"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string>1. Byte:</string> + </property> + <property name="buddy"> + <cstring>ui1Spin</cstring> + </property> + </widget> + </item> + <item> + <widget class="QSpinBox" name="ui1Spin"> + <property name="specialValueText"> + <string>broadcast</string> + </property> + <property name="maximum"> + <number>255</number> + </property> + <property name="value"> + <number>1</number> + </property> + </widget> + </item> + </layout> + </item> + </layout> + </item> + </layout> + </item> + <item row="1" column="0"> + <spacer name="verticalSpacer_5"> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + <property name="sizeType"> + <enum>QSizePolicy::Fixed</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>20</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item row="2" column="0" rowspan="2" colspan="3"> + <widget class="Line" name="line_4"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + </widget> + </item> + <item row="3" column="1"> + <spacer name="verticalSpacer_6"> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + <property name="sizeType"> + <enum>QSizePolicy::Fixed</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>20</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item row="4" column="0" colspan="3"> + <layout class="QGridLayout" name="gridLayout_5"> + <item row="0" column="0"> + <widget class="QLabel" name="fcTcpLabel"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Maximum" vsizetype="Preferred"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string>Function code:</string> + </property> + <property name="buddy"> + <cstring>fcTcpDrop</cstring> + </property> + </widget> + </item> + <item row="0" column="1"> + <widget class="QComboBox" name="fcTcpDrop"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <item> + <property name="text"> + <string>Type your custom function code and data below</string> + </property> + </item> + <item> + <property name="text"> + <string>0x01 - ReadCoils</string> + </property> + </item> + <item> + <property name="text"> + <string>0x02 - Read Discrete Inputs</string> + </property> + </item> + <item> + <property name="text"> + <string>0x03 - Read Holding Registers</string> + </property> + </item> + <item> + <property name="text"> + <string>0x04 - Read Input Registers</string> + </property> + </item> + <item> + <property name="text"> + <string>0x05 - Write Single Coil</string> + </property> + </item> + <item> + <property name="text"> + <string>0x06 - Write Single Register</string> + </property> + </item> + <item> + <property name="text"> + <string>0x07 - Read Exception Status</string> + </property> + </item> + <item> + <property name="text"> + <string>0x08 - Diagnostics</string> + </property> + </item> + <item> + <property name="text"> + <string>0x0B - Get Comm Event Counter</string> + </property> + </item> + <item> + <property name="text"> + <string>0x0C - Get Comm Event Log</string> + </property> + </item> + <item> + <property name="text"> + <string>0x0F - Write Multiple Coils</string> + </property> + </item> + <item> + <property name="text"> + <string>0x10 - Write Multiple Registers</string> + </property> + </item> + <item> + <property name="text"> + <string>0x11 - Report Server Id</string> + </property> + </item> + <item> + <property name="text"> + <string>0x14 - Read File Record</string> + </property> + </item> + <item> + <property name="text"> + <string>0x15 - Write File Record</string> + </property> + </item> + <item> + <property name="text"> + <string>0x16 - Mask Write Register</string> + </property> + </item> + <item> + <property name="text"> + <string>0x17 - Read/Write Multiple Registers</string> + </property> + </item> + <item> + <property name="text"> + <string>0x18 - Read Fifo Queue</string> + </property> + </item> + <item> + <property name="text"> + <string>0x2B - Encapsulated Interface Transport</string> + </property> + </item> + </widget> + </item> + <item row="1" column="0"> + <widget class="QLabel" name="pduTcpLabel"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Maximum" vsizetype="Preferred"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string>Data:</string> + </property> + <property name="buddy"> + <cstring>pduTcpLine</cstring> + </property> + </widget> + </item> + <item row="1" column="1"> + <widget class="QLineEdit" name="pduTcpLine"> + <property name="text"> + <string/> + </property> + <property name="placeholderText"> + <string>Hexadecimal representation of the data in big-endian byte order.</string> + </property> + </widget> + </item> + </layout> + </item> + <item row="5" column="2"> + <spacer name="verticalSpacer_2"> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>20</width> + <height>3</height> + </size> + </property> + </spacer> + </item> + </layout> + </widget> + </item> + </layout> + </widget> + </widget> + </item> + <item row="1" column="1"> + <layout class="QHBoxLayout" name="horizontalLayout_2"> + <item> + <spacer name="horizontalSpacer_5"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QPushButton" name="sendButton"> + <property name="enabled"> + <bool>false</bool> + </property> + <property name="sizePolicy"> + <sizepolicy hsizetype="Preferred" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string>Send</string> + </property> + </widget> + </item> + </layout> + </item> + <item row="2" column="0" colspan="2"> + <widget class="Line" name="line_2"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + </widget> + </item> + <item row="3" column="0" colspan="2"> + <widget class="PlainTextEdit" name="logTextEdit"> + <property name="undoRedoEnabled"> + <bool>false</bool> + </property> + <property name="readOnly"> + <bool>true</bool> + </property> + <property name="textInteractionFlags"> + <set>Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set> + </property> + </widget> + </item> + </layout> + </widget> + <widget class="QMenuBar" name="menubar"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>667</width> + <height>21</height> + </rect> + </property> + <widget class="QMenu" name="menuFile"> + <property name="title"> + <string>File</string> + </property> + <addaction name="actionExit"/> + </widget> + <widget class="QMenu" name="menuEdit"> + <property name="title"> + <string>Edit</string> + </property> + <addaction name="actionClear"/> + <addaction name="actionCopy"/> + <addaction name="separator"/> + <addaction name="actionSelect_All"/> + </widget> + <addaction name="menuFile"/> + <addaction name="menuEdit"/> + </widget> + <action name="actionExit"> + <property name="text"> + <string>Exit</string> + </property> + <property name="shortcut"> + <string>Alt+F4</string> + </property> + </action> + <action name="actionClear"> + <property name="text"> + <string>Clear</string> + </property> + </action> + <action name="actionCopy"> + <property name="text"> + <string>Copy</string> + </property> + <property name="shortcut"> + <string>Ctrl+C</string> + </property> + </action> + <action name="actionSelect_All"> + <property name="text"> + <string>Select All</string> + </property> + <property name="shortcut"> + <string>Ctrl+A</string> + </property> + </action> + </widget> + <customwidgets> + <customwidget> + <class>PlainTextEdit</class> + <extends>QPlainTextEdit</extends> + <header>plaintextedit.h</header> + </customwidget> + </customwidgets> + <tabstops> + <tabstop>serialRadio</tabstop> + <tabstop>serialPortCombo</tabstop> + <tabstop>parityCombo</tabstop> + <tabstop>dataBitsCombo</tabstop> + <tabstop>stopBitsCombo</tabstop> + <tabstop>baudRateCombo</tabstop> + <tabstop>tcpRadio</tabstop> + <tabstop>tcpPortEdit</tabstop> + <tabstop>tcpAddressEdit</tabstop> + <tabstop>retriesSpin</tabstop> + <tabstop>timeoutSpin</tabstop> + <tabstop>connectButton</tabstop> + <tabstop>disconnectButton</tabstop> + <tabstop>addressSpin</tabstop> + <tabstop>fcSerialDrop</tabstop> + <tabstop>pduSerialLine</tabstop> + <tabstop>ti1Spin</tabstop> + <tabstop>ti2Spin</tabstop> + <tabstop>pi1Spin</tabstop> + <tabstop>pi2Spin</tabstop> + <tabstop>l1Spin</tabstop> + <tabstop>l2Spin</tabstop> + <tabstop>ui1Spin</tabstop> + <tabstop>fcTcpDrop</tabstop> + <tabstop>pduTcpLine</tabstop> + <tabstop>sendButton</tabstop> + <tabstop>logTextEdit</tabstop> + </tabstops> + <resources/> + <connections> + <connection> + <sender>tcpRadio</sender> + <signal>toggled(bool)</signal> + <receiver>tcpPortEdit</receiver> + <slot>setEnabled(bool)</slot> + <hints> + <hint type="sourcelabel"> + <x>61</x> + <y>210</y> + </hint> + <hint type="destinationlabel"> + <x>199</x> + <y>236</y> + </hint> + </hints> + </connection> + <connection> + <sender>tcpRadio</sender> + <signal>toggled(bool)</signal> + <receiver>tcpAddressEdit</receiver> + <slot>setEnabled(bool)</slot> + <hints> + <hint type="sourcelabel"> + <x>61</x> + <y>210</y> + </hint> + <hint type="destinationlabel"> + <x>199</x> + <y>262</y> + </hint> + </hints> + </connection> + <connection> + <sender>serialRadio</sender> + <signal>toggled(bool)</signal> + <receiver>serialPortLabel</receiver> + <slot>setEnabled(bool)</slot> + <hints> + <hint type="sourcelabel"> + <x>68</x> + <y>57</y> + </hint> + <hint type="destinationlabel"> + <x>107</x> + <y>83</y> + </hint> + </hints> + </connection> + <connection> + <sender>tcpRadio</sender> + <signal>toggled(bool)</signal> + <receiver>tcpPortLabel</receiver> + <slot>setEnabled(bool)</slot> + <hints> + <hint type="sourcelabel"> + <x>61</x> + <y>210</y> + </hint> + <hint type="destinationlabel"> + <x>107</x> + <y>236</y> + </hint> + </hints> + </connection> + <connection> + <sender>tcpRadio</sender> + <signal>toggled(bool)</signal> + <receiver>tcpAddressLabel</receiver> + <slot>setEnabled(bool)</slot> + <hints> + <hint type="sourcelabel"> + <x>61</x> + <y>210</y> + </hint> + <hint type="destinationlabel"> + <x>107</x> + <y>262</y> + </hint> + </hints> + </connection> + <connection> + <sender>connectButton</sender> + <signal>clicked(bool)</signal> + <receiver>connectButton</receiver> + <slot>setEnabled(bool)</slot> + <hints> + <hint type="sourcelabel"> + <x>119</x> + <y>359</y> + </hint> + <hint type="destinationlabel"> + <x>119</x> + <y>359</y> + </hint> + </hints> + </connection> + <connection> + <sender>connectButton</sender> + <signal>clicked(bool)</signal> + <receiver>disconnectButton</receiver> + <slot>setDisabled(bool)</slot> + <hints> + <hint type="sourcelabel"> + <x>119</x> + <y>359</y> + </hint> + <hint type="destinationlabel"> + <x>200</x> + <y>359</y> + </hint> + </hints> + </connection> + <connection> + <sender>disconnectButton</sender> + <signal>clicked(bool)</signal> + <receiver>connectButton</receiver> + <slot>setDisabled(bool)</slot> + <hints> + <hint type="sourcelabel"> + <x>200</x> + <y>359</y> + </hint> + <hint type="destinationlabel"> + <x>119</x> + <y>359</y> + </hint> + </hints> + </connection> + <connection> + <sender>disconnectButton</sender> + <signal>clicked(bool)</signal> + <receiver>disconnectButton</receiver> + <slot>setEnabled(bool)</slot> + <hints> + <hint type="sourcelabel"> + <x>200</x> + <y>359</y> + </hint> + <hint type="destinationlabel"> + <x>200</x> + <y>359</y> + </hint> + </hints> + </connection> + <connection> + <sender>connectButton</sender> + <signal>clicked(bool)</signal> + <receiver>settingsWidget</receiver> + <slot>setEnabled(bool)</slot> + <hints> + <hint type="sourcelabel"> + <x>119</x> + <y>359</y> + </hint> + <hint type="destinationlabel"> + <x>133</x> + <y>135</y> + </hint> + </hints> + </connection> + <connection> + <sender>disconnectButton</sender> + <signal>clicked(bool)</signal> + <receiver>settingsWidget</receiver> + <slot>setDisabled(bool)</slot> + <hints> + <hint type="sourcelabel"> + <x>200</x> + <y>359</y> + </hint> + <hint type="destinationlabel"> + <x>133</x> + <y>135</y> + </hint> + </hints> + </connection> + <connection> + <sender>disconnectButton</sender> + <signal>clicked(bool)</signal> + <receiver>sendButton</receiver> + <slot>setEnabled(bool)</slot> + <hints> + <hint type="sourcelabel"> + <x>200</x> + <y>359</y> + </hint> + <hint type="destinationlabel"> + <x>656</x> + <y>368</y> + </hint> + </hints> + </connection> + <connection> + <sender>connectButton</sender> + <signal>clicked(bool)</signal> + <receiver>sendButton</receiver> + <slot>setDisabled(bool)</slot> + <hints> + <hint type="sourcelabel"> + <x>119</x> + <y>359</y> + </hint> + <hint type="destinationlabel"> + <x>656</x> + <y>368</y> + </hint> + </hints> + </connection> + <connection> + <sender>serialRadio</sender> + <signal>toggled(bool)</signal> + <receiver>serialPortCombo</receiver> + <slot>setEnabled(bool)</slot> + <hints> + <hint type="sourcelabel"> + <x>59</x> + <y>48</y> + </hint> + <hint type="destinationlabel"> + <x>155</x> + <y>70</y> + </hint> + </hints> + </connection> + <connection> + <sender>serialRadio</sender> + <signal>toggled(bool)</signal> + <receiver>parityLabel</receiver> + <slot>setEnabled(bool)</slot> + <hints> + <hint type="sourcelabel"> + <x>68</x> + <y>49</y> + </hint> + <hint type="destinationlabel"> + <x>68</x> + <y>100</y> + </hint> + </hints> + </connection> + <connection> + <sender>serialRadio</sender> + <signal>toggled(bool)</signal> + <receiver>dataBitsLabel</receiver> + <slot>setEnabled(bool)</slot> + <hints> + <hint type="sourcelabel"> + <x>36</x> + <y>48</y> + </hint> + <hint type="destinationlabel"> + <x>56</x> + <y>127</y> + </hint> + </hints> + </connection> + <connection> + <sender>serialRadio</sender> + <signal>toggled(bool)</signal> + <receiver>stopBitsLabel</receiver> + <slot>setEnabled(bool)</slot> + <hints> + <hint type="sourcelabel"> + <x>32</x> + <y>56</y> + </hint> + <hint type="destinationlabel"> + <x>53</x> + <y>157</y> + </hint> + </hints> + </connection> + <connection> + <sender>serialRadio</sender> + <signal>toggled(bool)</signal> + <receiver>baudRateLabel</receiver> + <slot>setEnabled(bool)</slot> + <hints> + <hint type="sourcelabel"> + <x>68</x> + <y>53</y> + </hint> + <hint type="destinationlabel"> + <x>68</x> + <y>177</y> + </hint> + </hints> + </connection> + <connection> + <sender>serialRadio</sender> + <signal>toggled(bool)</signal> + <receiver>parityCombo</receiver> + <slot>setEnabled(bool)</slot> + <hints> + <hint type="sourcelabel"> + <x>68</x> + <y>57</y> + </hint> + <hint type="destinationlabel"> + <x>135</x> + <y>102</y> + </hint> + </hints> + </connection> + <connection> + <sender>serialRadio</sender> + <signal>toggled(bool)</signal> + <receiver>dataBitsCombo</receiver> + <slot>setEnabled(bool)</slot> + <hints> + <hint type="sourcelabel"> + <x>68</x> + <y>56</y> + </hint> + <hint type="destinationlabel"> + <x>140</x> + <y>127</y> + </hint> + </hints> + </connection> + <connection> + <sender>serialRadio</sender> + <signal>toggled(bool)</signal> + <receiver>stopBitsCombo</receiver> + <slot>setEnabled(bool)</slot> + <hints> + <hint type="sourcelabel"> + <x>68</x> + <y>57</y> + </hint> + <hint type="destinationlabel"> + <x>135</x> + <y>153</y> + </hint> + </hints> + </connection> + <connection> + <sender>serialRadio</sender> + <signal>toggled(bool)</signal> + <receiver>baudRateCombo</receiver> + <slot>setEnabled(bool)</slot> + <hints> + <hint type="sourcelabel"> + <x>32</x> + <y>53</y> + </hint> + <hint type="destinationlabel"> + <x>129</x> + <y>179</y> + </hint> + </hints> + </connection> + <connection> + <sender>actionClear</sender> + <signal>triggered()</signal> + <receiver>logTextEdit</receiver> + <slot>clear()</slot> + <hints> + <hint type="sourcelabel"> + <x>-1</x> + <y>-1</y> + </hint> + <hint type="destinationlabel"> + <x>333</x> + <y>420</y> + </hint> + </hints> + </connection> + <connection> + <sender>actionSelect_All</sender> + <signal>triggered()</signal> + <receiver>logTextEdit</receiver> + <slot>selectAll()</slot> + <hints> + <hint type="sourcelabel"> + <x>-1</x> + <y>-1</y> + </hint> + <hint type="destinationlabel"> + <x>333</x> + <y>420</y> + </hint> + </hints> + </connection> + <connection> + <sender>actionCopy</sender> + <signal>triggered()</signal> + <receiver>logTextEdit</receiver> + <slot>copy()</slot> + <hints> + <hint type="sourcelabel"> + <x>-1</x> + <y>-1</y> + </hint> + <hint type="destinationlabel"> + <x>333</x> + <y>420</y> + </hint> + </hints> + </connection> + <connection> + <sender>actionSelect_All</sender> + <signal>triggered()</signal> + <receiver>logTextEdit</receiver> + <slot>setFocus()</slot> + <hints> + <hint type="sourcelabel"> + <x>-1</x> + <y>-1</y> + </hint> + <hint type="destinationlabel"> + <x>333</x> + <y>420</y> + </hint> + </hints> + </connection> + </connections> +</ui> diff --git a/examples/serialbus/modbus/adueditor/main.cpp b/examples/serialbus/modbus/adueditor/main.cpp new file mode 100644 index 0000000..1f3a7c8 --- /dev/null +++ b/examples/serialbus/modbus/adueditor/main.cpp @@ -0,0 +1,55 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the examples of the QtSerialBus module. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "mainwindow.h" + +#include <QApplication> + +QT_USE_NAMESPACE + +int main(int argc, char *argv[]) +{ + QApplication a(argc, argv); + + MainWindow w; + w.show(); + + return a.exec(); +} diff --git a/examples/serialbus/modbus/adueditor/mainwindow.cpp b/examples/serialbus/modbus/adueditor/mainwindow.cpp new file mode 100644 index 0000000..5cfb9cd --- /dev/null +++ b/examples/serialbus/modbus/adueditor/mainwindow.cpp @@ -0,0 +1,216 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the examples of the QtSerialBus module. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "mainwindow.h" +#include "modbustcpclient.h" + +#include <QLoggingCategory> +#include <QModbusRtuSerialMaster> +#include <QModbusPdu> +#include <QSerialPortInfo> + +QT_BEGIN_NAMESPACE +Q_LOGGING_CATEGORY(QT_MODBUS, "qt.modbus") +Q_LOGGING_CATEGORY(QT_MODBUS_LOW, "qt.modbus.lowlevel") +QT_END_NAMESPACE + +QT_USE_NAMESPACE + +MainWindow* s_instance = Q_NULLPTR; + +static void HandlerFunction(QtMsgType, const QMessageLogContext &, const QString &msg) +{ + if (auto instance = MainWindow::instance()) + instance->appendToLog(msg); +} + +MainWindow::MainWindow(QWidget *parent) + : QMainWindow(parent) + , m_debugHandler(HandlerFunction) +{ + setupUi(this); + s_instance = this; + + foreach (const QSerialPortInfo &info, QSerialPortInfo::availablePorts()) + serialPortCombo->addItem(info.portName(), true); + + connect(tcpRadio, &QRadioButton::toggled, this, [this](bool toggled) { + stackedWidget->setCurrentIndex(toggled); + }); + connect(actionExit, &QAction::triggered, this, &QMainWindow::close); + + QLoggingCategory::setFilterRules(QStringLiteral("qt.modbus* = true")); +} + +MainWindow::~MainWindow() +{ + disconnectAndDelete(); + s_instance = Q_NULLPTR; +} + +MainWindow* MainWindow::instance() +{ + return s_instance; +} + +void MainWindow::on_sendButton_clicked() +{ + const bool isSerial = serialRadio->isChecked(); + const bool isCustom = (isSerial ? fcSerialDrop : fcTcpDrop)->currentIndex() == 0; + const QByteArray pduData = QByteArray::fromHex((isSerial ? pduSerialLine : pduTcpLine)->text() + .toLatin1()); + + QModbusReply *reply = Q_NULLPTR; + if (isCustom && pduData.isEmpty()) { + qDebug() << "Error: Cannot send custom PDU without any data."; + return; + } + + const quint8 address = (isSerial ? addressSpin : ui1Spin)->value(); + if (isCustom) { + qDebug() << "Send: Sending custom PDU."; + reply = m_device->sendRawRequest(QModbusRequest(QModbusRequest::FunctionCode( + pduData[0]), pduData.mid(1)), address); + } else { + qDebug() << "Send: Sending PDU with predefined function code."; + reply = m_device->sendRawRequest(QModbusRequest(QModbusRequest::FunctionCode((isSerial + ? fcSerialDrop : fcTcpDrop)->currentIndex()), pduData), address); + } + + if (reply) { + sendButton->setDisabled(true); + if (!reply->isFinished()) { + connect(reply, &QModbusReply::finished, [reply, this]() { + sendButton->setEnabled(true); + qDebug() << "Receive: Asynchronous response PDU: " << reply->rawResult() << endl; + }); + } else { + sendButton->setEnabled(true); + qDebug() << "Receive: Synchronous response pdu: " << reply->rawResult() << endl; + } + } +} + +void MainWindow::on_connectButton_clicked() +{ + if (tcpRadio->isChecked()) { + ModbusTcpClient *device = new ModbusTcpClient; + using signature = void (QSpinBox::*)(int); + connect(ti1Spin, static_cast<signature>(&QSpinBox::valueChanged), device, + &ModbusTcpClient::valueChanged); + connect(ti2Spin, static_cast<signature>(&QSpinBox::valueChanged), device, + &ModbusTcpClient::valueChanged); + + connect(pi1Spin, static_cast<signature>(&QSpinBox::valueChanged), device, + &ModbusTcpClient::valueChanged); + connect(pi2Spin, static_cast<signature>(&QSpinBox::valueChanged), device, + &ModbusTcpClient::valueChanged); + + connect(l1Spin, static_cast<signature>(&QSpinBox::valueChanged), device, + &ModbusTcpClient::valueChanged); + connect(l2Spin, static_cast<signature>(&QSpinBox::valueChanged), device, + &ModbusTcpClient::valueChanged); + + connect(ui1Spin, static_cast<signature>(&QSpinBox::valueChanged), device, + &ModbusTcpClient::valueChanged); + + m_device = device; + device->valueChanged(0); // trigger update + m_device->setConnectionParameter(QModbusDevice::NetworkAddressParameter, + tcpAddressEdit->text()); + m_device->setConnectionParameter(QModbusDevice::NetworkPortParameter, + tcpPortEdit->text()); + } else { + m_device = new QModbusRtuSerialMaster; + m_device->setConnectionParameter(QModbusDevice::SerialPortNameParameter, + serialPortCombo->currentText()); + + int parity = parityCombo->currentIndex(); + if (parity > 0) + parity++; + m_device->setConnectionParameter(QModbusDevice::SerialParityParameter, parity); + m_device->setConnectionParameter(QModbusDevice::SerialDataBitsParameter, + dataBitsCombo->currentText().toInt()); + m_device->setConnectionParameter(QModbusDevice::SerialStopBitsParameter, + stopBitsCombo->currentText().toInt()); + m_device->setConnectionParameter(QModbusDevice::SerialBaudRateParameter, + baudRateCombo->currentText().toInt()); + } + m_device->setTimeout(timeoutSpin->value()); + m_device->setNumberOfRetries(retriesSpin->value()); + + connect(m_device, &QModbusDevice::errorOccurred, this, [this](QModbusDevice::ModbusError) { + qDebug().noquote() << QStringLiteral("Error: %1").arg(m_device->errorString()); + emit disconnectButton->clicked(); + }, Qt::QueuedConnection); + + connect(m_device, &QModbusDevice::stateChanged, [this](QModbusDevice::ModbusDeviceState state) { + switch (state) { + case QModbusDevice::UnconnectedState: + qDebug().noquote() << QStringLiteral("State: Entered unconnected state."); + break; + case QModbusDevice::ConnectingState: + qDebug().noquote() << QStringLiteral("State: Entered connecting state."); + break; + case QModbusDevice::ConnectedState: + qDebug().noquote() << QStringLiteral("State: Entered connected state."); + break; + case QModbusDevice::ClosingState: + qDebug().noquote() << QStringLiteral("State: Entered closing state."); + break; + } + }); + m_device->connectDevice(); +} + +void MainWindow::on_disconnectButton_clicked() +{ + disconnectAndDelete(); +} + +void MainWindow::disconnectAndDelete() +{ + if (!m_device) + return; + m_device->disconnectDevice(); + m_device->disconnect(); + delete m_device; + m_device = Q_NULLPTR; +} diff --git a/examples/serialbus/modbus/adueditor/mainwindow.h b/examples/serialbus/modbus/adueditor/mainwindow.h new file mode 100644 index 0000000..262eeee --- /dev/null +++ b/examples/serialbus/modbus/adueditor/mainwindow.h @@ -0,0 +1,94 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the examples of the QtSerialBus module. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef MAINWINDOW_H +#define MAINWINDOW_H + +#include "ui_interface.h" + +#include <QMainWindow> +#include <QObject> + +QT_BEGIN_NAMESPACE +class QModbusClient; +QT_END_NAMESPACE; + +class DebugHandler +{ +public: + DebugHandler() Q_DECL_EQ_DEFAULT; + DebugHandler(QtMessageHandler newMessageHandler) + : oldMessageHandler(qInstallMessageHandler(newMessageHandler)) + {} + ~DebugHandler() { qInstallMessageHandler(oldMessageHandler); } + +private: + QtMessageHandler oldMessageHandler; +}; + +class MainWindow : public QMainWindow, private Ui::MainWindow +{ + Q_OBJECT + Q_DISABLE_COPY(MainWindow) + friend class ModbusTcpClient; + +public: + explicit MainWindow(QWidget *parent = Q_NULLPTR); + ~MainWindow(); + + static MainWindow* instance(); + void appendToLog(const QString &msg) { + logTextEdit->appendPlainText(msg); + } + +private slots: + void on_sendButton_clicked(); + void on_connectButton_clicked(); + void on_disconnectButton_clicked(); + +private: + void disconnectAndDelete(); + +private: + DebugHandler m_debugHandler; + QModbusClient *m_device = Q_NULLPTR; +}; + +#endif // MAINWINDOW_H diff --git a/examples/serialbus/modbus/adueditor/modbustcpclient.cpp b/examples/serialbus/modbus/adueditor/modbustcpclient.cpp new file mode 100644 index 0000000..28067e9 --- /dev/null +++ b/examples/serialbus/modbus/adueditor/modbustcpclient.cpp @@ -0,0 +1,68 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the examples of the QtSerialBus module. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "mainwindow.h" +#include "modbustcpclient.h" +#include "modbustcpclient_p.h" + +QT_USE_NAMESPACE + +ModbusTcpClient::ModbusTcpClient(QObject *parent) + : QModbusTcpClient(*new ModbusTcpClientPrivate, parent) +{ +} + +ModbusTcpClient::ModbusTcpClient(ModbusTcpClientPrivate &dd, QObject *parent) + : QModbusTcpClient(dd, parent) +{ +} + +void ModbusTcpClient::valueChanged(int value) +{ + Q_UNUSED(value) + Q_D(ModbusTcpClient); + + if (auto instance = MainWindow::instance()) { + d->m_tId = quint16(instance->ti1Spin->value() << 8) | quint8(instance->ti2Spin->value()); + d->m_pId = quint16(instance->pi1Spin->value() << 8) | quint8(instance->pi2Spin->value()); + d->m_length = quint16(instance->l1Spin->value() << 8) | quint8(instance->l2Spin->value()); + d->m_uId = quint8(instance->ui1Spin->value()); + } +} diff --git a/examples/serialbus/modbus/adueditor/modbustcpclient.h b/examples/serialbus/modbus/adueditor/modbustcpclient.h new file mode 100644 index 0000000..8fea20c --- /dev/null +++ b/examples/serialbus/modbus/adueditor/modbustcpclient.h @@ -0,0 +1,65 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the examples of the QtSerialBus module. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef MODBUSTCPCLIENT_H +#define MODBUSTCPCLIENT_H + +#include <QModbusTcpClient> + +QT_USE_NAMESPACE + +class ModbusTcpClientPrivate; +class ModbusTcpClient : public QModbusTcpClient +{ + Q_OBJECT + Q_DISABLE_COPY(ModbusTcpClient) + Q_DECLARE_PRIVATE(ModbusTcpClient) + +public: + ModbusTcpClient(QObject *parent = Q_NULLPTR); + +public slots: + void valueChanged(int value); + +private: + ModbusTcpClient(ModbusTcpClientPrivate &dd, QObject *parent = Q_NULLPTR); +}; + +#endif // MODBUSTCPCLIENT_H diff --git a/examples/serialbus/modbus/adueditor/modbustcpclient_p.h b/examples/serialbus/modbus/adueditor/modbustcpclient_p.h new file mode 100644 index 0000000..4c52d98 --- /dev/null +++ b/examples/serialbus/modbus/adueditor/modbustcpclient_p.h @@ -0,0 +1,122 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the examples of the QtSerialBus module. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef MODBUSTCPCLIENT_P_H +#define MODBUSTCPCLIENT_P_H + +#include "modbustcpclient.h" + +#include <QDebug> +#include <QModbusReply> + +#include <private/qmodbustcpclient_p.h> + +QT_USE_NAMESPACE + +class ModbusTcpClientPrivate : private QModbusTcpClientPrivate +{ + Q_DECLARE_PUBLIC(ModbusTcpClient) + +public: + ModbusTcpClientPrivate() Q_DECL_EQ_DEFAULT; + + QModbusReply *enqueueRequest(const QModbusRequest &request, int, const QModbusDataUnit &unit, + QModbusReply::ReplyType type) Q_DECL_OVERRIDE + { + auto writeToSocket = [this](const QModbusRequest &request) { + QByteArray buffer; + QDataStream output(&buffer, QIODevice::WriteOnly); + output << m_tId << m_pId << m_length << m_uId << request; + + int writtenBytes = m_socket->write(buffer); + if (writtenBytes == -1 || writtenBytes < buffer.size()) { + Q_Q(ModbusTcpClient); + qDebug() << "Cannot write request to socket."; + q->setError(QModbusTcpClient::tr("Could not write request to socket."), + QModbusDevice::WriteError); + return false; + } + qCDebug(QT_MODBUS_LOW) << "Sent TCP ADU:" << buffer.toHex(); + qDebug() << "Sent TCP PDU:" << request << "with tId:" << hex << m_tId; + return true; + }; + + if (!writeToSocket(request)) + return Q_NULLPTR; + + Q_Q(ModbusTcpClient); + QModbusReply *const reply = new QModbusReply(type, m_uId, q); + const QueueElement element = QueueElement{ reply, request, unit, m_numberOfRetries, + m_responseTimeoutDuration }; + m_transactionStore.insert(m_tId, element); + + q->connect(q, &QModbusClient::timeoutChanged, element.timer.data(), &QTimer::setInterval); + QObject::connect(element.timer.data(), &QTimer::timeout, [this, writeToSocket]() { + if (!m_transactionStore.contains(m_tId)) + return; + + QueueElement elem = m_transactionStore.take(m_tId); + if (elem.reply.isNull()) + return; + + if (elem.numberOfRetries > 0) { + elem.numberOfRetries--; + if (!writeToSocket(elem.requestPdu)) + return; + m_transactionStore.insert(m_tId, elem); + elem.timer->start(); + qDebug() << "Resend request with tId:" << hex << m_tId; + } else { + qDebug() << "Timeout of request with tId:" << hex << m_tId; + elem.reply->setError(QModbusReply::TimeoutError, + QModbusClient::tr("Request timeout.")); + } + }); + element.timer->start(); + return reply; + } + + quint16 m_tId; + quint16 m_pId; + quint16 m_length; + quint8 m_uId; +}; + +#endif // MODBUSTCPCLIENT_P_H diff --git a/examples/serialbus/modbus/adueditor/plaintextedit.h b/examples/serialbus/modbus/adueditor/plaintextedit.h new file mode 100644 index 0000000..ed24d92 --- /dev/null +++ b/examples/serialbus/modbus/adueditor/plaintextedit.h @@ -0,0 +1,83 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the examples of the QtSerialBus module. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef PLAINTEXTEDIT_H +#define PLAINTEXTEDIT_H + +#include <QMenu> +#include <QPlainTextEdit> + +class PlainTextEdit : public QPlainTextEdit +{ + Q_OBJECT + Q_DISABLE_COPY(PlainTextEdit) + +public: + explicit PlainTextEdit(QWidget *parent = Q_NULLPTR) + : QPlainTextEdit(parent) + {} + + void keyPressEvent(QKeyEvent *e) + { + switch (e->key()) { + case Qt::Key_Delete: + case Qt::Key_Backspace: + setTextInteractionFlags(textInteractionFlags() | Qt::TextEditable); + QPlainTextEdit::keyPressEvent(e); + setTextInteractionFlags(textInteractionFlags() &~ Qt::TextEditable); + break; + default: + QPlainTextEdit::keyPressEvent(e); + } + } + + void contextMenuEvent(QContextMenuEvent *event) + { + QMenu menu(this); + menu.addAction(QStringLiteral("Clear"), this, &QPlainTextEdit::clear); + menu.addAction(QStringLiteral("Copy"), this, &QPlainTextEdit::copy, QKeySequence::Copy); + menu.addSeparator(); + menu.addAction(QStringLiteral("Select All"), this, &QPlainTextEdit::selectAll, + QKeySequence::SelectAll); + menu.exec(event->globalPos()); + } +}; + +#endif // PLAINTEXTEDIT_H diff --git a/examples/serialbus/modbus/modbus.pro b/examples/serialbus/modbus/modbus.pro index e427559..a15b828 100644 --- a/examples/serialbus/modbus/modbus.pro +++ b/examples/serialbus/modbus/modbus.pro @@ -2,4 +2,5 @@ TEMPLATE = subdirs SUBDIRS += \ master \ - slave + slave \ + adueditor diff --git a/src/serialbus/qmodbustcpclient_p.h b/src/serialbus/qmodbustcpclient_p.h index 648e164..563bb7b 100644 --- a/src/serialbus/qmodbustcpclient_p.h +++ b/src/serialbus/qmodbustcpclient_p.h @@ -94,13 +94,12 @@ public: { Q_Q(QModbusTcpClient); - q->setError(QModbusClient::tr("TCP socket error (%1).").arg(m_socket->errorString()), - QModbusDevice::ConnectionError); - if (m_socket->state() == QAbstractSocket::UnconnectedState) { cleanupTransactionStore(); q->setState(QModbusDevice::UnconnectedState); } + q->setError(QModbusClient::tr("TCP socket error (%1).").arg(m_socket->errorString()), + QModbusDevice::ConnectionError); }); QObject::connect(m_socket, &QIODevice::readyRead, [this](){ |