mirror of
https://github.com/nymea/nymea-plugins.git
synced 2026-07-17 00:36:35 +02:00
157 lines
7.3 KiB
C++
157 lines
7.3 KiB
C++
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
|
* *
|
|
* Copyright (C) 2019 Simon Stürz <simon.stuerz@guh.io> *
|
|
* *
|
|
* This file is part of nymea. *
|
|
* *
|
|
* This library is free software; you can redistribute it and/or *
|
|
* modify it under the terms of the GNU Lesser General Public *
|
|
* License as published by the Free Software Foundation; either *
|
|
* version 2.1 of the License, or (at your option) any later version. *
|
|
* *
|
|
* This library is distributed in the hope that it will be useful, *
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
|
* Lesser General Public License for more details. *
|
|
* *
|
|
* You should have received a copy of the GNU Lesser General Public *
|
|
* License along with this library; If not, see *
|
|
* <http://www.gnu.org/licenses/>. *
|
|
* *
|
|
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
|
|
|
#include "knxserverdiscovery.h"
|
|
#include "extern-plugininfo.h"
|
|
|
|
#include <QNetworkInterface>
|
|
#include <QKnxNetIpExtendedDeviceDibProxy>
|
|
|
|
KnxServerDiscovery::KnxServerDiscovery(QObject *parent) :
|
|
QObject(parent)
|
|
{
|
|
|
|
}
|
|
|
|
|
|
QList<QKnxNetIpServerInfo> KnxServerDiscovery::discoveredServers() const
|
|
{
|
|
return m_discoveredServers;
|
|
}
|
|
|
|
QString KnxServerDiscovery::serviceFamilyToString(QKnx::NetIp::ServiceFamily id)
|
|
{
|
|
switch (id) {
|
|
case QKnxNetIp::ServiceFamily::Core:
|
|
return "Core";
|
|
case QKnxNetIp::ServiceFamily::DeviceManagement:
|
|
return "Device Management";
|
|
case QKnxNetIp::ServiceFamily::IpTunneling:
|
|
return "Tunnel";
|
|
case QKnxNetIp::ServiceFamily::IpRouting:
|
|
return "Routing";
|
|
case QKnxNetIp::ServiceFamily::RemoteLogging:
|
|
return "Remote Logging";
|
|
case QKnxNetIp::ServiceFamily::RemoteConfigAndDiagnosis:
|
|
return "Remote Configuration";
|
|
case QKnxNetIp::ServiceFamily::ObjectServer:
|
|
return "Object Server";
|
|
case QKnxNetIp::ServiceFamily::Security:
|
|
return "Security";
|
|
default:
|
|
break;
|
|
}
|
|
return "Unknown";
|
|
}
|
|
|
|
void KnxServerDiscovery::printServerInfo(const QKnxNetIpServerInfo &serverInfo)
|
|
{
|
|
qCDebug(dcKnx()) << "Server:" << serverInfo.deviceName();
|
|
qCDebug(dcKnx()) << " Individual address:" << serverInfo.individualAddress().toString();
|
|
qCDebug(dcKnx()) << " Server control endpoint:" << QString("%1:%2").arg(serverInfo.controlEndpointAddress().toString()).arg(serverInfo.controlEndpointPort());
|
|
|
|
QVector<QKnxServiceInfo> services = serverInfo.supportedServices();
|
|
qCDebug(dcKnx()) << " Supported services:";
|
|
foreach (const QKnxServiceInfo &service, services)
|
|
qCDebug(dcKnx()) << " KNXnet/IP" << serviceFamilyToString(service.ServiceFamily) << ", Version:" << service.ServiceFamilyVersion;
|
|
|
|
qCDebug(dcKnx()) << " Mask version:" << serverInfo.maskVersion();
|
|
qCDebug(dcKnx()) << " Endpoint:" << serverInfo.endpoint();
|
|
|
|
QKnxNetIpDib dib = serverInfo.hardware();
|
|
QKnxNetIpExtendedDeviceDibProxy hardware(dib);
|
|
if (hardware.isValid()) {
|
|
qCDebug(dcKnx()) << " Extended hardware information:";
|
|
qCDebug(dcKnx()).noquote() << QString::fromLatin1(" Mask version: %1").arg(hardware.deviceDescriptorType0(), 4, 16, QLatin1Char('0'));
|
|
qCDebug(dcKnx()).noquote() << QString::fromLatin1(" Max. local APDU length: %1").arg(hardware.maximumLocalApduLength());
|
|
|
|
auto status = serverInfo.mediumStatus();
|
|
if (status == QKnx::MediumStatus::CommunicationPossible)
|
|
qCDebug(dcKnx()) << " Medium status: Communication possible";
|
|
else if (status == QKnx::MediumStatus::CommunicationImpossible)
|
|
qCDebug(dcKnx()) << " Medium status: Communication impossible";
|
|
else
|
|
qCDebug(dcKnx()) << " Medium status: Unknown";
|
|
}
|
|
}
|
|
|
|
void KnxServerDiscovery::onDiscoveryAgentErrorOccured(QKnxNetIpServerDiscoveryAgent::Error error)
|
|
{
|
|
QKnxNetIpServerDiscoveryAgent *discovery = static_cast<QKnxNetIpServerDiscoveryAgent *>(sender());
|
|
qCDebug(dcKnx()) << "Discovery error occured" << discovery->localAddress().toString() << error << discovery->errorString();
|
|
}
|
|
|
|
void KnxServerDiscovery::onDiscoveryAgentFinished()
|
|
{
|
|
QKnxNetIpServerDiscoveryAgent *discovery = static_cast<QKnxNetIpServerDiscoveryAgent *>(sender());
|
|
qCDebug(dcKnx()) << "Discovery agent for" << discovery->localAddress() << "has finished";
|
|
qCDebug(dcKnx()) << "Found" << discovery->discoveredServers().count() << "servers";
|
|
foreach (const QKnxNetIpServerInfo &serverInfo, discovery->discoveredServers()) {
|
|
m_discoveredServers.append(serverInfo);
|
|
}
|
|
|
|
m_runningDiscoveryAgents.removeAll(discovery);
|
|
discovery->deleteLater();
|
|
|
|
if (m_runningDiscoveryAgents.isEmpty()) {
|
|
emit discoveryFinished();
|
|
}
|
|
}
|
|
|
|
bool KnxServerDiscovery::startDisovery()
|
|
{
|
|
if (!m_runningDiscoveryAgents.isEmpty()) {
|
|
qCWarning(dcKnx()) << "Could not start discovery. There are still discovery agents running. (" << m_runningDiscoveryAgents.count() << "discoveries )";
|
|
return false;
|
|
}
|
|
|
|
qCDebug(dcKnx()) << "Start KNX server discovery on all interfaces";
|
|
m_discoveredServers.clear();
|
|
|
|
foreach (const QNetworkInterface &interface, QNetworkInterface::allInterfaces()) {
|
|
//qCDebug(dcKnx()) << "Checking network interface" << interface.name() << interface.type();
|
|
foreach (const QNetworkAddressEntry &addressEntry, interface.addressEntries()) {
|
|
// If ipv4 and not local host
|
|
if (addressEntry.ip().protocol() == QAbstractSocket::IPv4Protocol && !addressEntry.ip().isLoopback()) {
|
|
qCDebug(dcKnx()) << "Start discovery on" << interface.name() << addressEntry.ip().toString();
|
|
|
|
// Create discovery agent
|
|
QKnxNetIpServerDiscoveryAgent *discovery = new QKnxNetIpServerDiscoveryAgent(this);
|
|
discovery->setLocalAddress(addressEntry.ip());
|
|
discovery->setLocalPort(0);
|
|
discovery->setSearchFrequency(60);
|
|
discovery->setResponseType(QKnxNetIpServerDiscoveryAgent::ResponseType::Unicast);
|
|
discovery->setDiscoveryMode(QKnxNetIpServerDiscoveryAgent::DiscoveryMode::CoreV1 | QKnxNetIpServerDiscoveryAgent::DiscoveryMode::CoreV2);
|
|
|
|
connect(discovery, &QKnxNetIpServerDiscoveryAgent::finished, this, &KnxServerDiscovery::onDiscoveryAgentFinished);
|
|
connect(discovery, &QKnxNetIpServerDiscoveryAgent::errorOccurred, this, &KnxServerDiscovery::onDiscoveryAgentErrorOccured);
|
|
m_runningDiscoveryAgents.append(discovery);
|
|
|
|
// Start the discovery
|
|
discovery->start(m_discoveryTimeout);
|
|
}
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|