summaryrefslogtreecommitdiffstats
path: root/examples
diff options
context:
space:
mode:
authorAndrew O'Doherty <andrew.odoherty@qt.io>2018-08-20 13:57:28 +0200
committerKarsten Heimrich <karsten.heimrich@qt.io>2018-08-22 08:33:03 +0000
commitf31e56d388b98dc82cd158aec6047e7b6f1c1c4f (patch)
tree648c2de60b8bda93e7cdc92d3e81badbc03371d5 /examples
parent22fbb4a68b10e27fb921d7e6e36c8f45a0acfa2f (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.cpp151
-rw-r--r--examples/knx/knxeditor/tunnelingfeatures.h1
-rw-r--r--examples/knx/knxeditor/tunnelingfeatures.ui205
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/>