mirror of
https://github.com/nymea/nymea-plugins.git
synced 2026-10-23 14:43:44 +02:00
Merge PR #80: NetworkDetector: Improve monitoring, add a grace period parameter
This commit is contained in:
commit
94d131284c
1
debian/control
vendored
1
debian/control
vendored
@ -390,6 +390,7 @@ Architecture: any
|
|||||||
Depends: ${shlibs:Depends},
|
Depends: ${shlibs:Depends},
|
||||||
${misc:Depends},
|
${misc:Depends},
|
||||||
nmap,
|
nmap,
|
||||||
|
fping,
|
||||||
nymea-plugins-translations,
|
nymea-plugins-translations,
|
||||||
Replaces: guh-plugin-networkdetector
|
Replaces: guh-plugin-networkdetector
|
||||||
Description: nymea.io plugin for networkdetector
|
Description: nymea.io plugin for networkdetector
|
||||||
|
|||||||
51
networkdetector/broadcastping.cpp
Normal file
51
networkdetector/broadcastping.cpp
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
#include "broadcastping.h"
|
||||||
|
#include "extern-plugininfo.h"
|
||||||
|
|
||||||
|
#include <QNetworkInterface>
|
||||||
|
#include <QProcess>
|
||||||
|
|
||||||
|
BroadcastPing::BroadcastPing(QObject *parent) : QObject(parent)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void BroadcastPing::run()
|
||||||
|
{
|
||||||
|
qDeleteAll(m_runningPings.keys());
|
||||||
|
m_runningPings.clear();
|
||||||
|
|
||||||
|
foreach (const QNetworkInterface &interface, QNetworkInterface::allInterfaces()) {
|
||||||
|
if (!interface.flags().testFlag(QNetworkInterface::IsUp) || !interface.flags().testFlag(QNetworkInterface::CanBroadcast) || interface.flags().testFlag(QNetworkInterface::IsLoopBack)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
foreach (const QNetworkAddressEntry &addressEntry, interface.addressEntries()) {
|
||||||
|
if (addressEntry.broadcast().isNull()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
qCDebug(dcNetworkDetector()) << "Sending Broadcast Ping on" << addressEntry.broadcast().toString() + '/' + QString::number(addressEntry.prefixLength()) + "...";
|
||||||
|
QProcess *p = new QProcess(this);
|
||||||
|
m_runningPings.insert(p, addressEntry);
|
||||||
|
p->start("fping", {"-a", "-c", "1", "-g", addressEntry.broadcast().toString() + "/" + QString::number(addressEntry.prefixLength())});
|
||||||
|
connect(p, SIGNAL(finished(int)), this, SLOT(broadcastPingFinished(int)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (m_runningPings.isEmpty()) {
|
||||||
|
qCWarning(dcNetworkDetector()) << "Cound not find any suitable interface for broadcast pinging";
|
||||||
|
emit finished();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void BroadcastPing::broadcastPingFinished(int exitCode)
|
||||||
|
{
|
||||||
|
Q_UNUSED(exitCode);
|
||||||
|
QProcess *p = static_cast<QProcess*>(sender());
|
||||||
|
QNetworkAddressEntry addressEntry = m_runningPings.take(p);
|
||||||
|
qCDebug(dcNetworkDetector()) << "Broadcast ping finished for network" << addressEntry.broadcast().toString() + '/' + QString::number(addressEntry.prefixLength());
|
||||||
|
// qCDebug(dcNetworkDetector()) << p->readAllStandardError();
|
||||||
|
p->deleteLater();
|
||||||
|
|
||||||
|
if (m_runningPings.isEmpty()) {
|
||||||
|
qCDebug(dcNetworkDetector()) << "All broadcast pings finished";
|
||||||
|
emit finished();
|
||||||
|
}
|
||||||
|
}
|
||||||
28
networkdetector/broadcastping.h
Normal file
28
networkdetector/broadcastping.h
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
#ifndef BROADCASTPING_H
|
||||||
|
#define BROADCASTPING_H
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
#include <QHash>
|
||||||
|
#include <QProcess>
|
||||||
|
#include <QNetworkAddressEntry>
|
||||||
|
|
||||||
|
class BroadcastPing : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
explicit BroadcastPing(QObject *parent = nullptr);
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void finished();
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
void run();
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void broadcastPingFinished(int exitCode);
|
||||||
|
|
||||||
|
private:
|
||||||
|
QHash<QProcess*, QNetworkAddressEntry> m_runningPings;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // BROADCASTPING_H
|
||||||
@ -4,17 +4,20 @@
|
|||||||
|
|
||||||
#include <QNetworkInterface>
|
#include <QNetworkInterface>
|
||||||
|
|
||||||
DeviceMonitor::DeviceMonitor(const QString &macAddress, const QString &ipAddress, QObject *parent):
|
DeviceMonitor::DeviceMonitor(const QString &name, const QString &macAddress, const QString &ipAddress, bool initialState, QObject *parent):
|
||||||
QObject(parent)
|
QObject(parent),
|
||||||
|
m_name(name),
|
||||||
|
m_macAddress(macAddress),
|
||||||
|
m_ipAddress(ipAddress),
|
||||||
|
m_reachable(initialState)
|
||||||
{
|
{
|
||||||
m_host = new Host();
|
|
||||||
m_host->setMacAddress(macAddress);
|
|
||||||
m_host->setAddress(ipAddress);
|
|
||||||
m_host->setReachable(false);
|
|
||||||
|
|
||||||
m_arpLookupProcess = new QProcess(this);
|
m_arpLookupProcess = new QProcess(this);
|
||||||
connect(m_arpLookupProcess, SIGNAL(finished(int)), this, SLOT(arpLookupFinished(int)));
|
connect(m_arpLookupProcess, SIGNAL(finished(int)), this, SLOT(arpLookupFinished(int)));
|
||||||
|
|
||||||
|
m_arpingProcess = new QProcess(this);
|
||||||
|
m_arpingProcess->setReadChannelMode(QProcess::MergedChannels);
|
||||||
|
connect(m_arpingProcess, SIGNAL(finished(int)), this, SLOT(arpingFinished(int)));
|
||||||
|
|
||||||
m_pingProcess = new QProcess(this);
|
m_pingProcess = new QProcess(this);
|
||||||
m_pingProcess->setReadChannelMode(QProcess::MergedChannels);
|
m_pingProcess->setReadChannelMode(QProcess::MergedChannels);
|
||||||
connect(m_pingProcess, SIGNAL(finished(int)), this, SLOT(pingFinished(int)));
|
connect(m_pingProcess, SIGNAL(finished(int)), this, SLOT(pingFinished(int)));
|
||||||
@ -22,13 +25,17 @@ DeviceMonitor::DeviceMonitor(const QString &macAddress, const QString &ipAddress
|
|||||||
|
|
||||||
DeviceMonitor::~DeviceMonitor()
|
DeviceMonitor::~DeviceMonitor()
|
||||||
{
|
{
|
||||||
delete m_host;
|
}
|
||||||
|
|
||||||
|
void DeviceMonitor::setGracePeriod(int minutes)
|
||||||
|
{
|
||||||
|
m_gracePeriod = minutes;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DeviceMonitor::update()
|
void DeviceMonitor::update()
|
||||||
{
|
{
|
||||||
if (m_pingProcess->state() != QProcess::NotRunning) {
|
if (m_arpingProcess->state() != QProcess::NotRunning || m_pingProcess->state() != QProcess::NotRunning) {
|
||||||
qCDebug(dcNetworkDetector()) << "Previous ping still running for device" << m_host->address() << ". Not updating.";
|
// log("Previous ping still running. Not updating.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
lookupArpCache();
|
lookupArpCache();
|
||||||
@ -39,13 +46,94 @@ void DeviceMonitor::lookupArpCache()
|
|||||||
m_arpLookupProcess->start("ip", {"-4", "-s", "neighbor", "list"});
|
m_arpLookupProcess->start("ip", {"-4", "-s", "neighbor", "list"});
|
||||||
}
|
}
|
||||||
|
|
||||||
void DeviceMonitor::ping()
|
void DeviceMonitor::arpLookupFinished(int exitCode)
|
||||||
|
{
|
||||||
|
if (exitCode != 0) {
|
||||||
|
warn("Error looking up ARP cache.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString data = QString::fromLatin1(m_arpLookupProcess->readAll());
|
||||||
|
bool found = false;
|
||||||
|
bool needsPing = true;
|
||||||
|
QString mostRecentIP = m_ipAddress;
|
||||||
|
qlonglong secsSinceLastSeen = -1;
|
||||||
|
foreach (QString line, data.split('\n')) {
|
||||||
|
line.replace(QRegExp("[ ]{1,}"), " ");
|
||||||
|
QStringList parts = line.split(" ");
|
||||||
|
int lladdrIndex = parts.indexOf("lladdr");
|
||||||
|
if (lladdrIndex == -1 || parts.count() <= lladdrIndex) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
QString entryIP = parts.first();
|
||||||
|
QString entryMAC = parts.at(lladdrIndex + 1);
|
||||||
|
|
||||||
|
if (entryMAC.toLower() == m_macAddress.toLower()) {
|
||||||
|
found = true;
|
||||||
|
QString entryIP = parts.first();
|
||||||
|
if (parts.last() == "REACHABLE") {
|
||||||
|
log("Device found in ARP cache and claims to be REACHABLE (Cache IP: " + entryIP + ")");
|
||||||
|
if (!m_reachable) {
|
||||||
|
m_reachable = true;
|
||||||
|
emit reachableChanged(true);
|
||||||
|
}
|
||||||
|
emit seen();
|
||||||
|
m_lastSeenTime = QDateTime::currentDateTime();
|
||||||
|
// Verify if IP address is still the same
|
||||||
|
if (entryIP != mostRecentIP) {
|
||||||
|
mostRecentIP = entryIP;
|
||||||
|
}
|
||||||
|
// If we have a reachable entry, stop processing here
|
||||||
|
needsPing = false;
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
// ARP claims the device to be stale... Flagging device to require a ping.
|
||||||
|
log("Device found in ARP cache but is marked as " + parts.last() + " (Cache IP: " + entryIP + ")");
|
||||||
|
|
||||||
|
int usedIndex = parts.indexOf("used");
|
||||||
|
if (usedIndex >= 0 && parts.count() > usedIndex + 1) {
|
||||||
|
QString usedFields = parts.at(usedIndex + 1);
|
||||||
|
qlonglong newSecsSinceLastSeen = usedFields.split("/").first().toInt();
|
||||||
|
if (secsSinceLastSeen == -1 || newSecsSinceLastSeen < secsSinceLastSeen) {
|
||||||
|
secsSinceLastSeen = newSecsSinceLastSeen;
|
||||||
|
mostRecentIP = entryIP;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (entryIP == m_ipAddress) {
|
||||||
|
warn("There seems to be a device with our IP but different MAC. Resetting IP config.");
|
||||||
|
if (mostRecentIP == m_ipAddress) {
|
||||||
|
mostRecentIP.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (mostRecentIP != m_ipAddress) {
|
||||||
|
log("Device has changed IP: " + m_ipAddress + " -> " + mostRecentIP + ")");
|
||||||
|
m_ipAddress = mostRecentIP;
|
||||||
|
emit addressChanged(mostRecentIP);
|
||||||
|
}
|
||||||
|
if (m_ipAddress.isEmpty()) {
|
||||||
|
warn("Device not found in ARP cache and no IP config available. Marking as gone.");
|
||||||
|
if (m_reachable) {
|
||||||
|
m_reachable = false;
|
||||||
|
emit reachableChanged(false);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!found) {
|
||||||
|
log("Device not found in ARP cache.");
|
||||||
|
arping();
|
||||||
|
} else if (needsPing) {
|
||||||
|
arping();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DeviceMonitor::arping()
|
||||||
{
|
{
|
||||||
qCDebug(dcNetworkDetector()) << "Sending ARP Ping to" << m_host->hostName() << m_host->macAddress() << m_host->address();
|
|
||||||
QNetworkInterface targetInterface;
|
QNetworkInterface targetInterface;
|
||||||
foreach (const QNetworkInterface &interface, QNetworkInterface::allInterfaces()) {
|
foreach (const QNetworkInterface &interface, QNetworkInterface::allInterfaces()) {
|
||||||
foreach (const QNetworkAddressEntry &addressEntry, interface.addressEntries()) {
|
foreach (const QNetworkAddressEntry &addressEntry, interface.addressEntries()) {
|
||||||
QHostAddress clientAddress(m_host->address());
|
QHostAddress clientAddress(m_ipAddress);
|
||||||
if (clientAddress.isInSubnet(addressEntry.ip(), addressEntry.prefixLength())) {
|
if (clientAddress.isInSubnet(addressEntry.ip(), addressEntry.prefixLength())) {
|
||||||
targetInterface = interface;
|
targetInterface = interface;
|
||||||
break;
|
break;
|
||||||
@ -53,78 +141,62 @@ void DeviceMonitor::ping()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!targetInterface.isValid()) {
|
if (!targetInterface.isValid()) {
|
||||||
qCWarning(dcNetworkDetector()) << "Could not find a suitable interface to ping for" << m_host->address();
|
warn("Could not find a suitable interface to ARP Ping.");
|
||||||
if (m_host->reachable()) {
|
if (m_reachable) {
|
||||||
m_host->setReachable(false);
|
m_reachable = false;
|
||||||
emit reachableChanged(false);
|
emit reachableChanged(false);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_pingProcess->start("arping", {"-I", targetInterface.name(), "-f", "-w", "180", m_host->address()});
|
log("Sending ARP Ping to " + m_ipAddress + "...");
|
||||||
|
m_arpingProcess->start("arping", {"-I", targetInterface.name(), "-f", "-w", "30", m_ipAddress});
|
||||||
}
|
}
|
||||||
|
|
||||||
void DeviceMonitor::arpLookupFinished(int exitCode)
|
void DeviceMonitor::arpingFinished(int exitCode)
|
||||||
{
|
|
||||||
if (exitCode != 0) {
|
|
||||||
qCWarning(dcNetworkDetector()) << "Error looking up ARP cache.";
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
QString data = QString::fromLatin1(m_arpLookupProcess->readAll());
|
|
||||||
bool found = false;
|
|
||||||
bool needsPing = true;
|
|
||||||
foreach (QString line, data.split('\n')) {
|
|
||||||
line.replace(QRegExp("[ ]{1,}"), " ");
|
|
||||||
QStringList parts = line.split(" ");
|
|
||||||
int lladdrIndex = parts.indexOf("lladdr");
|
|
||||||
if (lladdrIndex >= 0 && parts.count() > lladdrIndex && parts.at(lladdrIndex+1).toLower() == m_host->macAddress().toLower()) {
|
|
||||||
found = true;
|
|
||||||
if (parts.last() == "REACHABLE") {
|
|
||||||
qCDebug(dcNetworkDetector()) << "Device" << m_host->macAddress() << "found in ARP cache and claims to be REACHABLE";
|
|
||||||
if (!m_host->reachable()) {
|
|
||||||
m_host->setReachable(true);
|
|
||||||
emit reachableChanged(true);
|
|
||||||
}
|
|
||||||
m_host->seen();
|
|
||||||
emit seen();
|
|
||||||
// Verify if IP address is still the same
|
|
||||||
if (parts.first() != m_host->address()) {
|
|
||||||
m_host->setAddress(parts.first());
|
|
||||||
emit addressChanged(parts.first());
|
|
||||||
}
|
|
||||||
// If we have a reachable entry, stop processing here
|
|
||||||
needsPing = false;
|
|
||||||
break;
|
|
||||||
} else {
|
|
||||||
// ARP claims the device to be stale... Flagging device to require a ping.
|
|
||||||
qCDebug(dcNetworkDetector()) << "Device" << m_host->macAddress() << "found in ARP cache but is marked as" << parts.last();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!found) {
|
|
||||||
qCDebug(dcNetworkDetector()) << "Device" << m_host->macAddress() << "not found in ARP cache.";
|
|
||||||
ping();
|
|
||||||
} else if (needsPing) {
|
|
||||||
ping();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void DeviceMonitor::pingFinished(int exitCode)
|
|
||||||
{
|
{
|
||||||
if (exitCode == 0) {
|
if (exitCode == 0) {
|
||||||
// we were able to ping the device
|
// we were able to ping the device
|
||||||
qCDebug(dcNetworkDetector()) << "Ping successful for" << m_host->macAddress() << m_host->address();
|
log("ARP Ping successful.");
|
||||||
m_host->seen();
|
if (!m_reachable) {
|
||||||
if (!m_host->reachable()) {
|
m_reachable = true;
|
||||||
m_host->setReachable(true);
|
|
||||||
emit reachableChanged(true);
|
emit reachableChanged(true);
|
||||||
}
|
}
|
||||||
emit seen();
|
emit seen();
|
||||||
|
m_lastSeenTime = QDateTime::currentDateTime();
|
||||||
} else {
|
} else {
|
||||||
qCDebug(dcNetworkDetector()) << "Could not ping device" << m_host->macAddress() << m_host->address();
|
log("ARP Ping failed.");
|
||||||
if (m_host->reachable()) {
|
ping();
|
||||||
m_host->setReachable(false);
|
}
|
||||||
|
// read data to discard it from socket
|
||||||
|
QString data = QString::fromLatin1(m_arpingProcess->readAll());
|
||||||
|
Q_UNUSED(data)
|
||||||
|
// qCDebug(dcNetworkDetector()) << "have ping data" << data;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DeviceMonitor::ping()
|
||||||
|
{
|
||||||
|
log("Sending ICMP Ping to " + m_ipAddress + "...");
|
||||||
|
m_pingProcess->start("ping", {"-c", "30", m_ipAddress});
|
||||||
|
}
|
||||||
|
|
||||||
|
void DeviceMonitor::pingFinished(int exitCode)
|
||||||
|
|
||||||
|
{
|
||||||
|
if (exitCode == 0) {
|
||||||
|
// we were able to ping the device
|
||||||
|
log("ICMP Ping successful.");
|
||||||
|
if (!m_reachable) {
|
||||||
|
m_reachable = true;
|
||||||
|
emit reachableChanged(true);
|
||||||
|
}
|
||||||
|
emit seen();
|
||||||
|
m_lastSeenTime = QDateTime::currentDateTime();
|
||||||
|
} else {
|
||||||
|
log("ICMP Ping failed.");
|
||||||
|
if (m_reachable && m_lastSeenTime.addSecs(m_gracePeriod * 60) < QDateTime::currentDateTime()) {
|
||||||
|
log("Exceeded grace period of " + QString::number(m_gracePeriod) + " minutes. Marking device as offline.");
|
||||||
|
m_reachable = false;
|
||||||
emit reachableChanged(false);
|
emit reachableChanged(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -133,3 +205,13 @@ void DeviceMonitor::pingFinished(int exitCode)
|
|||||||
Q_UNUSED(data)
|
Q_UNUSED(data)
|
||||||
// qCDebug(dcNetworkDetector()) << "have ping data" << data;
|
// qCDebug(dcNetworkDetector()) << "have ping data" << data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DeviceMonitor::log(const QString &message)
|
||||||
|
{
|
||||||
|
qCDebug(dcNetworkDetector()).noquote().nospace() << m_name << " (" << m_macAddress << ", " << m_ipAddress << "): " << message;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DeviceMonitor::warn(const QString &message)
|
||||||
|
{
|
||||||
|
qCWarning(dcNetworkDetector()).noquote().nospace() << m_name << " (" << m_macAddress << ", " << m_ipAddress << "): " << message;
|
||||||
|
}
|
||||||
|
|||||||
@ -3,17 +3,18 @@
|
|||||||
|
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
#include <QProcess>
|
#include <QProcess>
|
||||||
|
#include <QDateTime>
|
||||||
#include "host.h"
|
|
||||||
|
|
||||||
class DeviceMonitor : public QObject
|
class DeviceMonitor : public QObject
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
explicit DeviceMonitor(const QString &macAddress, const QString &ipAddress, QObject *parent = nullptr);
|
explicit DeviceMonitor(const QString &name, const QString &macAddress, const QString &ipAddress, bool initialState, QObject *parent = nullptr);
|
||||||
|
|
||||||
~DeviceMonitor();
|
~DeviceMonitor();
|
||||||
|
|
||||||
|
void setGracePeriod(int minutes);
|
||||||
|
|
||||||
void update();
|
void update();
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
@ -23,17 +24,29 @@ signals:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
void lookupArpCache();
|
void lookupArpCache();
|
||||||
|
void arping();
|
||||||
void ping();
|
void ping();
|
||||||
|
|
||||||
|
void log(const QString &message);
|
||||||
|
void warn(const QString &message);
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void arpLookupFinished(int exitCode);
|
void arpLookupFinished(int exitCode);
|
||||||
|
void arpingFinished(int exitCode);
|
||||||
void pingFinished(int exitCode);
|
void pingFinished(int exitCode);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Host *m_host;
|
QString m_name;
|
||||||
QProcess *m_arpLookupProcess;
|
QString m_macAddress;
|
||||||
QProcess *m_pingProcess;
|
QString m_ipAddress;
|
||||||
|
QDateTime m_lastSeenTime;
|
||||||
|
|
||||||
|
bool m_reachable = false;
|
||||||
|
int m_gracePeriod = 5;
|
||||||
|
|
||||||
|
QProcess *m_arpLookupProcess = nullptr;
|
||||||
|
QProcess *m_arpingProcess = nullptr;
|
||||||
|
QProcess *m_pingProcess = nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // DEVICEMONITOR_H
|
#endif // DEVICEMONITOR_H
|
||||||
|
|||||||
@ -57,12 +57,13 @@ DevicePluginNetworkDetector::DevicePluginNetworkDetector()
|
|||||||
{
|
{
|
||||||
m_discovery = new Discovery(this);
|
m_discovery = new Discovery(this);
|
||||||
connect(m_discovery, &Discovery::finished, this, &DevicePluginNetworkDetector::discoveryFinished);
|
connect(m_discovery, &Discovery::finished, this, &DevicePluginNetworkDetector::discoveryFinished);
|
||||||
|
|
||||||
|
m_broadcastPing = new BroadcastPing(this);
|
||||||
|
connect(m_broadcastPing, &BroadcastPing::finished, this, &DevicePluginNetworkDetector::broadcastPingFinished);
|
||||||
}
|
}
|
||||||
|
|
||||||
DevicePluginNetworkDetector::~DevicePluginNetworkDetector()
|
DevicePluginNetworkDetector::~DevicePluginNetworkDetector()
|
||||||
{
|
{
|
||||||
hardwareManager()->pluginTimerManager()->unregisterTimer(m_pluginTimer);
|
|
||||||
|
|
||||||
if (m_discovery->isRunning()) {
|
if (m_discovery->isRunning()) {
|
||||||
m_discovery->abort();
|
m_discovery->abort();
|
||||||
}
|
}
|
||||||
@ -70,19 +71,27 @@ DevicePluginNetworkDetector::~DevicePluginNetworkDetector()
|
|||||||
|
|
||||||
void DevicePluginNetworkDetector::init()
|
void DevicePluginNetworkDetector::init()
|
||||||
{
|
{
|
||||||
m_pluginTimer = hardwareManager()->pluginTimerManager()->registerTimer(10);
|
|
||||||
connect(m_pluginTimer, &PluginTimer::timeout, this, &DevicePluginNetworkDetector::onPluginTimer);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
DeviceManager::DeviceSetupStatus DevicePluginNetworkDetector::setupDevice(Device *device)
|
DeviceManager::DeviceSetupStatus DevicePluginNetworkDetector::setupDevice(Device *device)
|
||||||
{
|
{
|
||||||
qCDebug(dcNetworkDetector()) << "Setup" << device->name() << device->params();
|
qCDebug(dcNetworkDetector()) << "Setup" << device->name() << device->params();
|
||||||
DeviceMonitor *monitor = new DeviceMonitor(device->paramValue(networkDeviceDeviceMacAddressParamTypeId).toString(), device->paramValue(networkDeviceDeviceAddressParamTypeId).toString(), this);
|
DeviceMonitor *monitor = new DeviceMonitor(device->name(),
|
||||||
|
device->paramValue(networkDeviceDeviceMacAddressParamTypeId).toString(),
|
||||||
|
device->paramValue(networkDeviceDeviceAddressParamTypeId).toString(),
|
||||||
|
device->stateValue(networkDeviceIsPresentStateTypeId).toBool(),
|
||||||
|
this);
|
||||||
connect(monitor, &DeviceMonitor::reachableChanged, this, &DevicePluginNetworkDetector::deviceReachableChanged);
|
connect(monitor, &DeviceMonitor::reachableChanged, this, &DevicePluginNetworkDetector::deviceReachableChanged);
|
||||||
connect(monitor, &DeviceMonitor::addressChanged, this, &DevicePluginNetworkDetector::deviceAddressChanged);
|
connect(monitor, &DeviceMonitor::addressChanged, this, &DevicePluginNetworkDetector::deviceAddressChanged);
|
||||||
connect(monitor, &DeviceMonitor::seen, this, &DevicePluginNetworkDetector::deviceSeen);
|
connect(monitor, &DeviceMonitor::seen, this, &DevicePluginNetworkDetector::deviceSeen);
|
||||||
m_monitors.insert(monitor, device);
|
m_monitors.insert(monitor, device);
|
||||||
monitor->update();
|
|
||||||
|
if (!m_pluginTimer) {
|
||||||
|
m_pluginTimer = hardwareManager()->pluginTimerManager()->registerTimer(30);
|
||||||
|
connect(m_pluginTimer, &PluginTimer::timeout, m_broadcastPing, &BroadcastPing::run);
|
||||||
|
|
||||||
|
m_broadcastPing->run();
|
||||||
|
}
|
||||||
|
|
||||||
return DeviceManager::DeviceSetupStatusSuccess;
|
return DeviceManager::DeviceSetupStatusSuccess;
|
||||||
}
|
}
|
||||||
@ -110,9 +119,15 @@ void DevicePluginNetworkDetector::deviceRemoved(Device *device)
|
|||||||
DeviceMonitor *monitor = m_monitors.key(device);
|
DeviceMonitor *monitor = m_monitors.key(device);
|
||||||
m_monitors.remove(monitor);
|
m_monitors.remove(monitor);
|
||||||
delete monitor;
|
delete monitor;
|
||||||
|
|
||||||
|
if (m_monitors.isEmpty()) {
|
||||||
|
hardwareManager()->pluginTimerManager()->unregisterTimer(m_pluginTimer);
|
||||||
|
m_pluginTimer = nullptr;
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void DevicePluginNetworkDetector::onPluginTimer()
|
void DevicePluginNetworkDetector::broadcastPingFinished()
|
||||||
{
|
{
|
||||||
foreach (DeviceMonitor *monitor, m_monitors.keys()) {
|
foreach (DeviceMonitor *monitor, m_monitors.keys()) {
|
||||||
monitor->update();
|
monitor->update();
|
||||||
@ -124,7 +139,15 @@ void DevicePluginNetworkDetector::discoveryFinished(const QList<Host> &hosts)
|
|||||||
qCDebug(dcNetworkDetector()) << "Discovery finished. Found" << hosts.count() << "devices";
|
qCDebug(dcNetworkDetector()) << "Discovery finished. Found" << hosts.count() << "devices";
|
||||||
QList<DeviceDescriptor> discoveredDevices;
|
QList<DeviceDescriptor> discoveredDevices;
|
||||||
foreach (const Host &host, hosts) {
|
foreach (const Host &host, hosts) {
|
||||||
DeviceDescriptor descriptor(networkDeviceDeviceClassId, (host.hostName().isEmpty() ? host.address() : host.hostName() + "(" + host.address() + ")"), host.macAddress());
|
|
||||||
|
DeviceDescriptor descriptor(networkDeviceDeviceClassId, host.hostName().isEmpty() ? host.address() : host.hostName(), host.address() + " (" + host.macAddress() + ")");
|
||||||
|
|
||||||
|
foreach (Device *existingDevice, myDevices()) {
|
||||||
|
if (existingDevice->paramValue(networkDeviceDeviceMacAddressParamTypeId).toString() == host.macAddress()) {
|
||||||
|
descriptor.setDeviceId(existingDevice->id());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ParamList paramList;
|
ParamList paramList;
|
||||||
Param macAddress(networkDeviceDeviceMacAddressParamTypeId, host.macAddress());
|
Param macAddress(networkDeviceDeviceMacAddressParamTypeId, host.macAddress());
|
||||||
|
|||||||
@ -29,6 +29,7 @@
|
|||||||
#include "discovery.h"
|
#include "discovery.h"
|
||||||
#include "plugintimer.h"
|
#include "plugintimer.h"
|
||||||
#include "devicemonitor.h"
|
#include "devicemonitor.h"
|
||||||
|
#include "broadcastping.h"
|
||||||
|
|
||||||
#include <QProcess>
|
#include <QProcess>
|
||||||
#include <QXmlStreamReader>
|
#include <QXmlStreamReader>
|
||||||
@ -59,11 +60,12 @@ private slots:
|
|||||||
void deviceAddressChanged(const QString &address);
|
void deviceAddressChanged(const QString &address);
|
||||||
void deviceSeen();
|
void deviceSeen();
|
||||||
|
|
||||||
void onPluginTimer();
|
void broadcastPingFinished();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
PluginTimer *m_pluginTimer = nullptr;
|
PluginTimer *m_pluginTimer = nullptr;
|
||||||
Discovery *m_discovery = nullptr;
|
Discovery *m_discovery = nullptr;
|
||||||
|
BroadcastPing *m_broadcastPing = nullptr;
|
||||||
QHash<DeviceMonitor*, Device*> m_monitors;
|
QHash<DeviceMonitor*, Device*> m_monitors;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -34,6 +34,13 @@
|
|||||||
"displayName": "hardware address",
|
"displayName": "hardware address",
|
||||||
"type": "QString",
|
"type": "QString",
|
||||||
"inputType": "TextLine"
|
"inputType": "TextLine"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "40116f86-e6b3-4a20-b1e9-e1bd4b6d5b70",
|
||||||
|
"name": "gracePeriod",
|
||||||
|
"displayName": "Grace period (Minutes)",
|
||||||
|
"type": "uint",
|
||||||
|
"defaultValue": 5
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"stateTypes": [
|
"stateTypes": [
|
||||||
|
|||||||
@ -8,12 +8,14 @@ SOURCES += \
|
|||||||
devicepluginnetworkdetector.cpp \
|
devicepluginnetworkdetector.cpp \
|
||||||
host.cpp \
|
host.cpp \
|
||||||
discovery.cpp \
|
discovery.cpp \
|
||||||
devicemonitor.cpp
|
devicemonitor.cpp \
|
||||||
|
broadcastping.cpp
|
||||||
|
|
||||||
HEADERS += \
|
HEADERS += \
|
||||||
devicepluginnetworkdetector.h \
|
devicepluginnetworkdetector.h \
|
||||||
host.h \
|
host.h \
|
||||||
discovery.h \
|
discovery.h \
|
||||||
devicemonitor.h
|
devicemonitor.h \
|
||||||
|
broadcastping.h
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user