diff options
author | Andrew O'Doherty <andrew.odoherty@qt.io> | 2018-08-20 13:57:28 +0200 |
---|---|---|
committer | Karsten Heimrich <karsten.heimrich@qt.io> | 2018-08-22 08:33:03 +0000 |
commit | f31e56d388b98dc82cd158aec6047e7b6f1c1c4f (patch) | |
tree | 648c2de60b8bda93e7cdc92d3e81badbc03371d5 /examples | |
parent | 22fbb4a68b10e27fb921d7e6e36c8f45a0acfa2f (diff) |
Cleanup KNX editor tunneling features tab
Change-Id: I8077d65b877abfb07c59476cafe832e5f516236d
Reviewed-by: Karsten Heimrich <karsten.heimrich@qt.io>
Diffstat (limited to 'examples')
-rw-r--r-- | examples/knx/knxeditor/tunnelingfeatures.cpp | 151 | ||||
-rw-r--r-- | examples/knx/knxeditor/tunnelingfeatures.h | 1 | ||||
-rw-r--r-- | examples/knx/knxeditor/tunnelingfeatures.ui | 205 |
3 files changed, 255 insertions, 102 deletions
diff --git a/examples/knx/knxeditor/tunnelingfeatures.cpp b/examples/knx/knxeditor/tunnelingfeatures.cpp index d1e3282..851cc5f 100644 --- a/examples/knx/knxeditor/tunnelingfeatures.cpp +++ b/examples/knx/knxeditor/tunnelingfeatures.cpp @@ -33,6 +33,35 @@ #include <QtCore/QMetaEnum> #include <QtCore/QMetaType> #include <QtKnx/QKnx1Bit> +#include <QtKnx/QKnx> +#include <QtKnx/QKnxUtils> + +bool validFeature(const QKnx::NetIp::ServiceType &frameType, const QKnx::InterfaceFeature &feature, + const QKnxByteArray &value) +{ + using ServType = QKnx::NetIp::ServiceType; + if (frameType != ServType::TunnelingFeatureSet) + return true; + + using FeatureType = QKnx::InterfaceFeature; + switch (feature) { + case FeatureType::SupportedEmiType: + case FeatureType::HostDeviceDescriptorType0: + case FeatureType::KnxManufacturerCode: + case FeatureType::IndividualAddress: + case FeatureType::MaximumApduLength: + return value.size() == 2; + case FeatureType::BusConnectionStatus: + case FeatureType::InterfaceFeatureInfoServiceEnable: + return value.size() == 1 && ((value.at(0) == 0x01) || (value.at(0) == 0x00)); + case FeatureType::ActiveEmiType: + return value.size() == 1; + default: + break; + } + + return false; +} TunnelingFeatures::TunnelingFeatures(QWidget *parent) : QWidget(parent) @@ -40,6 +69,10 @@ TunnelingFeatures::TunnelingFeatures(QWidget *parent) { ui->setupUi(this); + ui->tunnelServiceType->setEnabled(false); + ui->featureIdentifier->setEnabled(false); + ui->featureValue->setEnabled(false); + connect(ui->connectTunneling, &QPushButton::clicked, this, [&]() { ui->textOuputTunneling->append(tr("Connecting to: %1 on port: %2 protocol: %3").arg(m_server .controlEndpointAddress().toString()).arg(m_server.controlEndpointPort()).arg(int(m_protocol))); @@ -51,17 +84,24 @@ TunnelingFeatures::TunnelingFeatures(QWidget *parent) connect(ui->tunnelingSend, &QPushButton::clicked, this, [&]() { using ServType = QKnx::NetIp::ServiceType; - ServType type = ServType(quint16(ServType::TunnelingFeatureGet) - + ui->tunnelServiceType->currentIndex()); + ServType type = ServType(quint16(ServType::TunnelingFeatureGet)); + if (ui->tunnelServiceType->currentIndex() == 1) + type = ServType(quint16(ServType::TunnelingFeatureSet)); + using FeatureType = QKnx::InterfaceFeature; FeatureType featureType = FeatureType(quint8(FeatureType::SupportedEmiType) + ui->featureIdentifier->currentIndex()); - QKnx1Bit featureEnable(true); + + QKnxByteArray bytes = QKnxByteArray::fromHex(ui->featureValue->text().toUtf8()); QKnxNetIpFrame frame; + if (type == ServType::TunnelingFeatureGet) m_tunnel.sendTunnelingFeatureGet(featureType); else if (type == ServType::TunnelingFeatureSet) - m_tunnel.sendTunnelingFeatureSet(featureType, featureEnable.bytes()); + m_tunnel.sendTunnelingFeatureSet(featureType, bytes); + + ui->statusBar->setText(tr("Status: (%1) Messages sent.").arg(m_tunnel + .sequenceCount(QKnxNetIpEndpointConnection::SequenceType::Send) + 1)); }); connect(&m_tunnel, &QKnxNetIpTunnel::tunnelingFeatureInfoReceived, this, @@ -87,17 +127,48 @@ TunnelingFeatures::TunnelingFeatures(QWidget *parent) auto metaEnum = QMetaEnum::fromType<QKnx::InterfaceFeature>(); auto metaReturnCode = QMetaEnum::fromType<QKnx::ReturnCode>(); - if (feature == QKnx::InterfaceFeature::InterfaceFeatureInfoServiceEnable) { + if (feature == QKnx::InterfaceFeature::InterfaceFeatureInfoServiceEnable + || feature == QKnx::InterfaceFeature::BusConnectionStatus) { auto state = QKnxSwitch::State(value.at(0)); auto metaEnumState = QMetaEnum::fromType<QKnxSwitch::State>(); ui->textOuputTunneling->append(tr("Received Tunneling Feature Response: Feature (%1), " - "Return Code(%2), Value (%3)") + "Return Code (%2), Value (%3)") .arg(QString::fromLatin1(metaEnum.valueToKey(int(feature)))) .arg(QString::fromLatin1(metaReturnCode.valueToKey(int(code)))) .arg(QString::fromLatin1(metaEnumState.valueToKey(int(state))))); + } else if (feature == QKnx::InterfaceFeature::IndividualAddress) { + ui->textOuputTunneling->append(tr("Received Tunneling Feature Response: Feature (%1), " + "Return Code (%2), Individual Address Value (%3)") + .arg(QString::fromLatin1(metaEnum.valueToKey(int(feature)))) + .arg(QString::fromLatin1(metaReturnCode.valueToKey(int(code)))) + .arg(QKnxAddress(QKnxAddress::Type::Individual, value).toString())); + } else if (feature == QKnx::InterfaceFeature::KnxManufacturerCode + || feature == QKnx::InterfaceFeature::MaximumApduLength) { + ui->textOuputTunneling->append(tr("Received Tunneling Feature Response: Feature (%1), " + "Return Code (%2), Value (%3)") + .arg(QString::fromLatin1(metaEnum.valueToKey(int(feature)))) + .arg(QString::fromLatin1(metaReturnCode.valueToKey(int(code)))) + .arg(QKnxUtils::QUint16::fromBytes(value))); + } else if (feature == QKnx::InterfaceFeature::ActiveEmiType + || feature == QKnx::InterfaceFeature::SupportedEmiType) { + QString str; + auto types = QKnx::EmiTypes(value.at(0)); + auto metaEmiType = QMetaEnum::fromType<QKnx::EmiType>(); + if (types.testFlag(QKnx::EmiType::EMI1)) + str = QLatin1String(metaEmiType.valueToKey(int(QKnx::EmiType::EMI1))); + if (types.testFlag(QKnx::EmiType::EMI2)) + str += "|" + QLatin1String(metaEmiType.valueToKey(int(QKnx::EmiType::EMI2))); + if (types.testFlag(QKnx::EmiType::cEMI)) + str += "|" + QLatin1String(metaEmiType.valueToKey(int(QKnx::EmiType::cEMI))); + ui->textOuputTunneling->append(tr("Received Tunneling Feature Response: Feature (%1), " + "Return Code (%2), EMI (%3)") + .arg(QString::fromLatin1(metaEnum.valueToKey(int(feature)))) + .arg(QString::fromLatin1(metaReturnCode.valueToKey(int(code)))) + .arg(str.isEmpty() ? QLatin1String(metaEmiType.valueToKey(int(QKnx::EmiType::Unknown))) + : str)); } else { ui->textOuputTunneling->append(tr("Received Tunneling Feature Response: Feature (%1), " - "Return Code(%2), Value: ") + "Return Code (%2), Value: ") .arg(metaEnum.valueToKey(int(feature))) .arg(QString::fromLatin1(metaReturnCode.valueToKey(int(code)))) + QLatin1String(value.toByteArray(), value.size())); @@ -107,10 +178,19 @@ TunnelingFeatures::TunnelingFeatures(QWidget *parent) connect(&m_tunnel, &QKnxNetIpTunnel::connected, this, [&] { ui->connectTunneling->setEnabled(false); ui->disconnectTunneling->setEnabled(true); - ui->tunnelingSend->setEnabled(true); - + ui->tunnelServiceType->setEnabled(true); + ui->featureIdentifier->setEnabled(true); + if (ui->tunnelServiceType->currentText() == "TunnelingFeatureSet") { + ui->featureValue->setEnabled(true); + ui->tunnelingSend->setEnabled(!ui->featureValue->text().isEmpty()); + } else { + ui->featureValue->setEnabled(false); + ui->tunnelingSend->setEnabled(true); + } ui->textOuputTunneling->append(tr("Successfully connected to: %1 on port: %2").arg(m_server .controlEndpointAddress().toString()).arg(m_server.controlEndpointPort())); + + ui->statusBar->setText("Status: Connected."); }); connect(ui->disconnectTunneling, &QPushButton::clicked, this, [&]() { @@ -121,14 +201,37 @@ TunnelingFeatures::TunnelingFeatures(QWidget *parent) ui->connectTunneling->setEnabled(true); ui->disconnectTunneling->setEnabled(false); ui->tunnelingSend->setEnabled(false); + ui->tunnelServiceType->setEnabled(false); + ui->featureIdentifier->setEnabled(false); + ui->featureValue->setEnabled(false); ui->textOuputTunneling->append(tr("Successfully disconnected from: %1 on port: %2\n") .arg(m_server.controlEndpointAddress().toString()).arg(m_server.controlEndpointPort())); + ui->statusBar->setText("Status: Disconnected."); }); connect(&m_tunnel, &QKnxNetIpTunnel::errorOccurred, this, [&] (QKnxNetIpEndpointConnection::Error, QString errorString) { ui->textOuputTunneling->append(errorString); }); + + connect(ui->tunnelServiceType, &QComboBox::currentTextChanged, this, [&](const QString &text) { + if (text == QString("TunnelingFeatureSet")) { + ui->featureValue->setEnabled(true); + ui->statusBar->setText("Status: Fill in the feature type and value fields."); + } else { + ui->featureValue->setEnabled(false); + ui->statusBar->setText(""); + } + checkFeatureValue(); + }); + + connect(ui->featureValue, &QLineEdit::textChanged, this, [&](const QString &) { + checkFeatureValue(); + }); + + connect(ui->featureIdentifier, &QComboBox::currentTextChanged, this, [&](const QString &) { + checkFeatureValue(); + }); } TunnelingFeatures::~TunnelingFeatures() @@ -157,9 +260,39 @@ void TunnelingFeatures::setKnxNetIpServer(const QKnxNetIpServerInfo &server) ui->disconnectTunneling->setEnabled(false); } ui->tunnelingSend->setEnabled(false); + ui->statusBar->setText("Status: Start by clicking connect."); } void TunnelingFeatures::setTcpEnable(bool value) { m_protocol = (value ? QKnxNetIp::HostProtocol::TCP_IPv4 : QKnxNetIp::HostProtocol::UDP_IPv4); } + +void TunnelingFeatures::checkFeatureValue() +{ + if (!ui->featureValue->isEnabled()) { + ui->statusBar->setText(""); + ui->tunnelingSend->setEnabled(m_tunnel.state() == QKnxNetIpEndpointConnection::State::Connected); + return; + } + + using ServType = QKnx::NetIp::ServiceType; + ServType type = ServType(quint16(ServType::TunnelingFeatureGet)); + if (ui->tunnelServiceType->currentIndex() == 1) + type = ServType(quint16(ServType::TunnelingFeatureSet)); + + using FeatureType = QKnx::InterfaceFeature; + FeatureType featureType = FeatureType(quint8(FeatureType::SupportedEmiType) + + ui->featureIdentifier->currentIndex()); + + QKnxByteArray bytes = QKnxByteArray::fromHex(ui->featureValue->text().toUtf8()); + auto text = ui->featureValue->text(); + if (text.isEmpty() || !validFeature(type, featureType, bytes) + || ((text.size() % 2) != 0)) { + ui->statusBar->setText("Status: Invalid value entered"); + ui->tunnelingSend->setEnabled(false); + return; + } + ui->statusBar->setText("Status: Valid value entered, click send."); + ui->tunnelingSend->setEnabled(m_tunnel.state() == QKnxNetIpEndpointConnection::State::Connected); +} diff --git a/examples/knx/knxeditor/tunnelingfeatures.h b/examples/knx/knxeditor/tunnelingfeatures.h index 2af5444..8c93667 100644 --- a/examples/knx/knxeditor/tunnelingfeatures.h +++ b/examples/knx/knxeditor/tunnelingfeatures.h @@ -55,6 +55,7 @@ public: void setTcpEnable(bool value); private: + void checkFeatureValue(); Ui::TunnelingFeatures *ui; QKnxNetIpServerInfo m_server; diff --git a/examples/knx/knxeditor/tunnelingfeatures.ui b/examples/knx/knxeditor/tunnelingfeatures.ui index dcdb613..50abfc8 100644 --- a/examples/knx/knxeditor/tunnelingfeatures.ui +++ b/examples/knx/knxeditor/tunnelingfeatures.ui @@ -6,31 +6,40 @@ <rect> <x>0</x> <y>0</y> - <width>1612</width> - <height>669</height> + <width>856</width> + <height>385</height> </rect> </property> <property name="windowTitle"> <string>Form</string> </property> - <layout class="QVBoxLayout" name="verticalLayout_4" stretch="0,0,1,0"> - <item> - <layout class="QHBoxLayout" name="horizontalLayout_2" stretch="0,0,0"> - <property name="spacing"> - <number>10</number> - </property> - <property name="sizeConstraint"> - <enum>QLayout::SetDefaultConstraint</enum> - </property> - <item alignment="Qt::AlignHCenter"> + <layout class="QGridLayout" name="gridLayout_2"> + <item row="0" column="0" colspan="4"> + <layout class="QGridLayout" name="gridLayout" columnstretch="0,1,0,0"> + <item row="0" column="0"> <widget class="QLabel" name="label_13"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Maximum" vsizetype="Preferred"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> <property name="text"> <string>Tunnelling Service Type:</string> </property> </widget> </item> - <item alignment="Qt::AlignLeft"> + <item row="0" column="1"> <widget class="QComboBox" name="tunnelServiceType"> + <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="iconSize"> <size> <width>200</width> @@ -44,56 +53,38 @@ </item> <item> <property name="text"> - <string>TunnelingFeatureResponse</string> - </property> - </item> - <item> - <property name="text"> <string>TunnelingFeatureSet</string> </property> </item> - <item> - <property name="text"> - <string>TunnelingFeatureInfo</string> - </property> - </item> </widget> </item> - <item> - <spacer name="horizontalSpacer"> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>40</width> - <height>20</height> - </size> - </property> - </spacer> - </item> - </layout> - </item> - <item> - <layout class="QHBoxLayout" name="horizontalLayout"> - <item> + <item row="1" column="0"> <widget class="QLabel" name="label"> - <property name="minimumSize"> - <size> - <width>260</width> - <height>0</height> - </size> + <property name="sizePolicy"> + <sizepolicy hsizetype="Maximum" vsizetype="Preferred"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> </property> <property name="text"> <string>Feature Identifier:</string> </property> </widget> </item> - <item> + <item row="1" column="1"> <widget class="QComboBox" name="featureIdentifier"> + <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>350</width> + <width>0</width> <height>0</height> </size> </property> @@ -103,6 +94,9 @@ <height>16777215</height> </size> </property> + <property name="autoFillBackground"> + <bool>false</bool> + </property> <item> <property name="text"> <string>Supported EMI type</string> @@ -135,7 +129,7 @@ </item> <item> <property name="text"> - <string>Max. APDU Length</string> + <string>Maximum APDU Length</string> </property> </item> <item> @@ -145,8 +139,28 @@ </item> </widget> </item> - <item> - <spacer name="horizontalSpacer_3"> + <item row="2" column="0"> + <widget class="QLabel" name="label_2"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Maximum" vsizetype="Preferred"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string>Feature value (HEX):</string> + </property> + </widget> + </item> + <item row="2" column="1"> + <widget class="QLineEdit" name="featureValue"> + <property name="enabled"> + <bool>false</bool> + </property> + </widget> + </item> + <item row="2" column="2"> + <spacer name="horizontalSpacer_5"> <property name="orientation"> <enum>Qt::Horizontal</enum> </property> @@ -158,9 +172,19 @@ </property> </spacer> </item> + <item row="2" column="3"> + <widget class="QPushButton" name="tunnelingSend"> + <property name="enabled"> + <bool>false</bool> + </property> + <property name="text"> + <string>Send Message</string> + </property> + </widget> + </item> </layout> </item> - <item> + <item row="1" column="0" colspan="4"> <widget class="QTextEdit" name="textOuputTunneling"> <property name="focusPolicy"> <enum>Qt::StrongFocus</enum> @@ -179,51 +203,46 @@ </property> </widget> </item> - <item> - <layout class="QHBoxLayout" name="horizontalLayout_4"> - <item> - <widget class="QPushButton" name="tunnelingSend"> - <property name="text"> - <string>Send Message</string> - </property> - </widget> - </item> - <item> - <spacer name="horizontalSpacer_2"> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - <property name="sizeType"> - <enum>QSizePolicy::Fixed</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>40</width> - <height>20</height> - </size> - </property> - </spacer> - </item> - <item> - <widget class="QPushButton" name="connectTunneling"> - <property name="text"> - <string>Connect</string> - </property> - </widget> - </item> - <item> - <widget class="QPushButton" name="disconnectTunneling"> - <property name="text"> - <string>Disconnect</string> - </property> - </widget> - </item> - </layout> + <item row="2" column="0"> + <widget class="QLabel" name="statusBar"> + <property name="text"> + <string/> + </property> + </widget> + </item> + <item row="2" column="1"> + <spacer name="horizontalSpacer_2"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeType"> + <enum>QSizePolicy::Expanding</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>662</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item row="2" column="2"> + <widget class="QPushButton" name="connectTunneling"> + <property name="text"> + <string>Connect</string> + </property> + </widget> + </item> + <item row="2" column="3"> + <widget class="QPushButton" name="disconnectTunneling"> + <property name="text"> + <string>Disconnect</string> + </property> + </widget> </item> </layout> </widget> <tabstops> - <tabstop>tunnelingSend</tabstop> <tabstop>disconnectTunneling</tabstop> </tabstops> <resources/> |