summaryrefslogtreecommitdiffstats
path: root/tradeshow/knx-demo/3d-Alexa-knx-demo/qmlknxdemo.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'tradeshow/knx-demo/3d-Alexa-knx-demo/qmlknxdemo.cpp')
-rw-r--r--tradeshow/knx-demo/3d-Alexa-knx-demo/qmlknxdemo.cpp362
1 files changed, 362 insertions, 0 deletions
diff --git a/tradeshow/knx-demo/3d-Alexa-knx-demo/qmlknxdemo.cpp b/tradeshow/knx-demo/3d-Alexa-knx-demo/qmlknxdemo.cpp
new file mode 100644
index 0000000..b6e3d50
--- /dev/null
+++ b/tradeshow/knx-demo/3d-Alexa-knx-demo/qmlknxdemo.cpp
@@ -0,0 +1,362 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt 3D Studio Demos.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, 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 "demodatapoint.h"
+#include "qmlknxdemo.h"
+#include "utils.h"
+
+#include <QtCore/QString>
+#include <QtGui/QColor>
+#include <QtKnx/QKnxAddress>
+#include <QtNetwork/QNetworkAddressEntry>
+#include <QtNetwork/QNetworkInterface>
+
+namespace {
+ const double sliderSectionSize = 1 / 7.0;
+ using DeviceNumbers = EtsDevelopmentBoard::DeviceNumbers;
+}
+
+QmlKnxDemo::QmlKnxDemo()
+ : m_tunnel(this)
+{
+ checkLightStatusOn();
+
+ if (auto blind = m_etsBoard.getBlind()) {
+ connect(blind, &DemoBlindDataPoint::blindChange, this, &QmlKnxDemo::blindPositionChange);
+ connect(blind, &DemoBlindDataPoint::blindFullyUp, this, &QmlKnxDemo::blindFullyUp);
+ connect(blind, &DemoBlindDataPoint::blindFullyDown, this, &QmlKnxDemo::blindFullyDown);
+ }
+
+ if (auto rocker = m_etsBoard.getRocker())
+ connect(rocker, &DemoRockerDataPoint::rockerChange, this, &QmlKnxDemo::rockerChange);
+
+ if (auto colorLed = m_etsBoard.getColorLed())
+ connect(colorLed, &DemoColorLed::colorChange, this, &QmlKnxDemo::colorLedChange);
+}
+
+void QmlKnxDemo::toggleLight(int light)
+{
+ if (auto dpt = static_cast<DemoSwitchDataPoint *>(m_etsBoard.getGroupObject(light))) {
+ dpt->uiToggle();
+ sendGroupValueWrite(m_tunnel, m_etsBoard.getAddress(light), dpt->bytes());
+ }
+}
+
+void QmlKnxDemo::colorSwitch(double value)
+{
+ QColor colorAtStart = colorState;
+ if (value < (sliderSectionSize / 2)
+ && colorState != Qt::black)
+ colorState = Qt::black;
+
+ else if ((value > (sliderSectionSize / 2))
+ && value < (3 * sliderSectionSize / 2)
+ && (colorState != Qt::white))
+ colorState = Qt::white;
+
+ else if ((value > (3 * sliderSectionSize / 2))
+ && value < (5 * sliderSectionSize / 2)
+ && (colorState != Qt::red))
+ colorState = Qt::red;
+
+ else if ((value > (5 * sliderSectionSize / 2))
+ && value < (7 * sliderSectionSize / 2)
+ && (colorState != Qt::magenta))
+ colorState = Qt::magenta;
+
+ else if ((value > (7 * sliderSectionSize / 2))
+ && value < (9 * sliderSectionSize / 2)
+ && (colorState != Qt::blue))
+ colorState = Qt::blue;
+
+ else if ((value > (9 * sliderSectionSize / 2))
+ && value < (11 * sliderSectionSize / 2)
+ && (colorState != Qt::cyan))
+ colorState = Qt::cyan;
+
+ else if (value > (11 * sliderSectionSize / 2)
+ && value < (13 * sliderSectionSize / 2)
+ && (colorState != Qt::green))
+ colorState = Qt::green;
+
+ else if (value > ((6 * sliderSectionSize) + (sliderSectionSize / 2))
+ && (colorState != Qt::yellow))
+ colorState = Qt::yellow;
+
+ if (colorAtStart != colorState) {
+ if (auto led = m_etsBoard.getColorLed()) {
+ led->setCurrentColor(colorState);
+ sendColorLedGroupValueWriteFrames(m_tunnel, led);
+ }
+ }
+}
+
+void QmlKnxDemo::toggleMiddleRight()
+{
+ auto light = DeviceNumbers::MIDDLE_RIGHT;
+ if (auto dpt = static_cast<DemoSwitchDataPoint *>(m_etsBoard.getGroupObject(light))) {
+ dpt->uiToggle();
+ sendGroupValueWrite(m_tunnel, m_etsBoard.getAddress(light), dpt->bytes());
+ }
+}
+
+void QmlKnxDemo::toggleMiddleLeft()
+{
+ auto led = m_etsBoard.getColorLed();
+ if (!led)
+ return;
+
+ if (!led->isOn()) {
+ // set green color in dpt by default...
+ led->setCurrentColor(QColor(0, 255, 0));
+ // send request to ets board
+ sendColorLedGroupValueWriteFrames(m_tunnel, led);
+ } else {
+ led->setCurrentColor(QColor(0, 0, 0));
+ sendColorLedGroupValueWriteFrames(m_tunnel, led);
+ }
+}
+
+QString QmlKnxDemo::getColor() const
+{
+ if (auto obj = m_etsBoard.getColorLed())
+ return obj->currentColor().name();
+ return {};
+}
+
+int QmlKnxDemo::getRockerPosition() const
+{
+ if (auto rocker = m_etsBoard.getRocker())
+ return rocker->position();
+ return 0;
+}
+
+bool QmlKnxDemo::getLightState(int lightNum) const
+{
+ if (auto dpt = static_cast<DemoSwitchDataPoint *>(m_etsBoard.getGroupObject(lightNum)))
+ return dpt->isOn();
+ return false;
+}
+
+int QmlKnxDemo::getBlindPosition() const
+{
+ if (auto blind = m_etsBoard.getBlind())
+ return blind->position();
+ return 0;
+}
+
+void QmlKnxDemo::moveBlindUp()
+{
+ if (auto dpt = m_etsBoard.getBlind()) {
+ sendGroupValueWrite(m_tunnel, m_etsBoard.getAddress(DeviceNumbers::E7), dpt->moveUpBytes(),
+ 0xac);
+ }
+}
+
+void QmlKnxDemo::moveBlindDown()
+{
+ if (auto dpt = m_etsBoard.getBlind()) {
+ sendGroupValueWrite(m_tunnel, m_etsBoard.getAddress(DeviceNumbers::E7), dpt->moveDownBytes(),
+ 0xac);
+ }
+}
+
+void QmlKnxDemo::stopBlind()
+{
+ auto index = DeviceNumbers::E16;
+ if (auto dpt = static_cast<DemoBlindDataPoint *>(m_etsBoard.getGroupObject(index)))
+ sendGroupValueWrite(m_tunnel, m_etsBoard.getAddress(index), dpt->stopBytes(), 0xac);
+}
+
+void QmlKnxDemo::handleFrame(const QKnxTunnelFrame &frame)
+{
+ auto str = frame.serviceInformation().bytes().toHex();
+ auto dstAdd = frame.destinationAddress().toString();
+
+ if (QKnxCemiFrame::MessageCode::DataConfirmation == frame.messageCode()
+ || QKnxCemiFrame::MessageCode::DataIndication == frame.messageCode()) {
+ // data indication come from pushing buttons on the Board
+ // data confirmation are responses to App UI requests
+ bool boardStateChanged = false;
+ const QKnxAddress dstAddress = frame.destinationAddress();
+ if (m_etsBoard.exists(dstAddress))
+ boardStateChanged = m_etsBoard.getGroupObject(dstAddress)->updateDataPointState(frame);
+
+ if (boardStateChanged)
+ emit boardUpdate(m_etsBoard.getIndex(dstAddress));
+ }
+}
+
+static QHostAddress obtainLocalAddress()
+{
+ auto addresses = QNetworkInterface::allAddresses();
+ for (auto address : qAsConst(addresses)) {
+ if (address.isLoopback() || address.protocol() != QAbstractSocket::IPv4Protocol)
+ continue;
+ qDebug() << "using IP " << address;
+ return address;
+ }
+ qDebug() << "using loopback IP!!!";
+ return QHostAddress::LocalHost; // no local address found!
+}
+
+QmlKnxTunnel::QmlKnxTunnel(QmlKnxDemo *demo)
+{
+ connect(&m_connection, &QKnxNetIpTunnelConnection::stateChanged,
+ this, &QmlKnxTunnel::handleConnection);
+ connect(&m_connection, &QKnxNetIpTunnelConnection::receivedTunnelFrame,
+ demo, &QmlKnxDemo::handleFrame);
+ connect(&m_timer, &QTimer::timeout, this, &QmlKnxTunnel::send);
+ auto newAddress = obtainLocalAddress();
+ m_connection.setLocalAddress(newAddress);
+ m_discoveryAgent.setLocalAddress(newAddress);
+ m_ip.setAddress("192.168.1.50");
+ m_port = 3671;
+ reconnect();
+ qDebug() << " m_ip" << m_ip;
+ // Automatic KNXnet/Ip router discovery. Connects to first router found
+ static auto handleDiscoveredServer = [&](const QKnxNetIpServerInfo &info) {
+ if (!m_connected) {
+ m_ip = info.controlEndpointAddress();
+ m_port = info.controlEndpointPort();
+ // establish the knx tunnel
+ reconnect();
+ m_connected = true;
+ }
+ };
+ connect(&m_discoveryAgent, &QKnxNetIpServerDiscoveryAgent::deviceDiscovered, this,
+ handleDiscoveredServer);
+ autoDiscoverKnxServers();
+}
+
+void QmlKnxTunnel::sendTunnelFrame(const QKnxCemiFrame &frame)
+{
+ if (frame.size() == 0)
+ return;
+
+ if (m_frames.size() == 0)
+ m_timer.start(200);
+ m_frames.enqueue(frame);
+}
+
+void QmlKnxTunnel::reconnect()
+{
+ m_connection.connectToHost(m_ip, m_port);
+}
+
+void QmlKnxTunnel::autoDiscoverKnxServers()
+{
+ if (m_connection.state() != m_connection.Connected) {
+ m_discoveryAgent.stop();
+ m_connected = false;
+ m_discoveryAgent.start();
+ }
+}
+
+void QmlKnxTunnel::changeIp(const QString &ip, quint16 port)
+{
+ m_ip = ip;
+ m_port = port;
+ m_connection.disconnectFromHost();
+}
+
+void QmlKnxTunnel::send()
+{
+ m_connection.sendTunnelFrame(m_frames.dequeue());
+ if (m_frames.size() == 0)
+ m_timer.stop();
+}
+
+void QmlKnxTunnel::handleConnection(QKnxNetIpEndpointConnection::State state)
+{
+ switch (state) {
+ case QKnxNetIpEndpointConnection::State::Disconnected:
+ autoDiscoverKnxServers();
+ break;
+ default:
+ break;
+ }
+}
+
+void QmlKnxDemo::changeTunnelIp(const QString &ipStr, quint16 port)
+{
+ m_tunnel.changeIp(ipStr, port);
+}
+
+void QmlKnxDemo::changeRoom(int roomId)
+{
+ currentRoom = roomId;
+ emit roomChanged(currentRoom);
+}
+
+void QmlKnxDemo::checkLightStatusOn()
+{
+ initBoard(m_etsBoard, m_tunnel);
+}
+
+void QmlKnxDemo::test()
+{
+ static int c = 0;
+ if (c == 0)
+ emit colorLedChange(QColor("blue"));
+ else if (c==1)
+ emit colorLedChange(QColor("magenta"));
+ else if (c==2) {
+ emit colorLedChange(QColor("green"));
+ c = 0;
+ return;
+ }
+ c++;
+}
+
+void QmlKnxDemo::reconnect()
+{
+ m_tunnel.reconnect();
+}