From 96d38c1b2e48b5cf7d454a71db9ce2819bea02e2 Mon Sep 17 00:00:00 2001 From: Michael Zanetti Date: Thu, 20 Dec 2018 22:26:11 +0100 Subject: [PATCH 1/5] implement presencesensor in networkdetector --- networkdetector/devicemonitor.cpp | 2 ++ networkdetector/devicemonitor.h | 1 + .../devicepluginnetworkdetector.cpp | 9 +++++++++ networkdetector/devicepluginnetworkdetector.h | 1 + .../devicepluginnetworkdetector.json | 20 ++++++++++++++++++- 5 files changed, 32 insertions(+), 1 deletion(-) diff --git a/networkdetector/devicemonitor.cpp b/networkdetector/devicemonitor.cpp index 648abd28..1ae8d850 100644 --- a/networkdetector/devicemonitor.cpp +++ b/networkdetector/devicemonitor.cpp @@ -66,6 +66,7 @@ void DeviceMonitor::arpLookupFinished(int exitCode) m_host->setReachable(true); emit reachableChanged(true); } + emit seen(); } else { // ARP claims the device to be stale... try to ping it. qCDebug(dcNetworkDetector()) << "Device" << m_host->macAddress() << "found in ARP cache but is marked as" << parts.last() << ". Trying to ping it on" << m_host->address(); @@ -95,6 +96,7 @@ void DeviceMonitor::pingFinished(int exitCode) m_host->setReachable(true); emit reachableChanged(true); } + emit seen(); } else { qDebug(dcNetworkDetector()) << "Could not ping device" << m_host->macAddress() << m_host->address(); } diff --git a/networkdetector/devicemonitor.h b/networkdetector/devicemonitor.h index f1f1d9c4..28fce3bd 100644 --- a/networkdetector/devicemonitor.h +++ b/networkdetector/devicemonitor.h @@ -19,6 +19,7 @@ public: signals: void addressChanged(const QString &address); void reachableChanged(bool reachable); + void seen(); private: void lookupArpCache(); diff --git a/networkdetector/devicepluginnetworkdetector.cpp b/networkdetector/devicepluginnetworkdetector.cpp index abf36c6d..4cada1ce 100644 --- a/networkdetector/devicepluginnetworkdetector.cpp +++ b/networkdetector/devicepluginnetworkdetector.cpp @@ -80,6 +80,7 @@ DeviceManager::DeviceSetupStatus DevicePluginNetworkDetector::setupDevice(Device DeviceMonitor *monitor = new DeviceMonitor(device->paramValue(networkDeviceDeviceMacAddressParamTypeId).toString(), device->paramValue(networkDeviceDeviceAddressParamTypeId).toString(), this); connect(monitor, &DeviceMonitor::reachableChanged, this, &DevicePluginNetworkDetector::deviceReachableChanged); connect(monitor, &DeviceMonitor::addressChanged, this, &DevicePluginNetworkDetector::deviceAddressChanged); + connect(monitor, &DeviceMonitor::seen, this, &DevicePluginNetworkDetector::deviceSeen); m_monitors.insert(monitor, device); return DeviceManager::DeviceSetupStatusSuccess; @@ -144,6 +145,7 @@ void DevicePluginNetworkDetector::deviceReachableChanged(bool reachable) if (device->stateValue(networkDeviceConnectedStateTypeId).toBool() != reachable) { qCDebug(dcNetworkDetector()) << "Device" << device->paramValue(networkDeviceDeviceMacAddressParamTypeId).toString() << "reachable changed" << reachable; device->setStateValue(networkDeviceConnectedStateTypeId, reachable); + device->setStateValue(networkDeviceIsPresentStateTypeId, reachable); } } @@ -155,3 +157,10 @@ void DevicePluginNetworkDetector::deviceAddressChanged(const QString &address) device->setParamValue(networkDeviceDeviceAddressParamTypeId.toString(), address); } } + +void DevicePluginNetworkDetector::deviceSeen() +{ + DeviceMonitor *monitor = static_cast(sender()); + Device *device = m_monitors.value(monitor); + device->setStateValue(networkDeviceLastSeenTimeStateTypeId, QDateTime::currentDateTime().toTime_t()); +} diff --git a/networkdetector/devicepluginnetworkdetector.h b/networkdetector/devicepluginnetworkdetector.h index 4c861d80..197d0a7c 100644 --- a/networkdetector/devicepluginnetworkdetector.h +++ b/networkdetector/devicepluginnetworkdetector.h @@ -57,6 +57,7 @@ private slots: void deviceReachableChanged(bool reachable); void deviceAddressChanged(const QString &address); + void deviceSeen(); void onPluginTimer(); diff --git a/networkdetector/devicepluginnetworkdetector.json b/networkdetector/devicepluginnetworkdetector.json index 49175dfd..a8d303af 100644 --- a/networkdetector/devicepluginnetworkdetector.json +++ b/networkdetector/devicepluginnetworkdetector.json @@ -17,7 +17,7 @@ "Device", "Sensor" ], - "interfaces": ["connectable"], + "interfaces": [ "connectable", "presencesensor" ], "primaryStateTypeId": "cb43e1b5-4f61-4538-bfa2-c33055c542cf", "createMethods": ["user", "discovery"], "paramTypes": [ @@ -45,6 +45,24 @@ "type": "bool", "defaultValue": false, "cached": false + }, + { + "id": "0a38651c-418d-42b3-80f5-6e7adb6a25fc", + "name": "isPresent", + "displayName": "Device is present", + "displayNameEvent": "Device is present changed", + "type": "bool", + "defaultValue": false, + "cached": false + }, + { + "id": "b51d54c9-cce1-43f0-a35d-52fc2d8d302c", + "name": "lastSeenTime", + "displayName": "Last seen time", + "displayNameEvent": "Last seen time changed", + "type": "int", + "unit": "UnixTime", + "defaultValue": 0 } ] } From 7b68afbaa893e7ef70c1acd77cda45205a05a456 Mon Sep 17 00:00:00 2001 From: Michael Zanetti Date: Sun, 30 Dec 2018 23:38:55 +0100 Subject: [PATCH 2/5] use arping instead of ping --- networkdetector/devicemonitor.cpp | 29 +++++++++++++++---- .../devicepluginnetworkdetector.cpp | 6 ++-- .../devicepluginnetworkdetector.json | 11 +------ 3 files changed, 27 insertions(+), 19 deletions(-) diff --git a/networkdetector/devicemonitor.cpp b/networkdetector/devicemonitor.cpp index 1ae8d850..7c0eaed0 100644 --- a/networkdetector/devicemonitor.cpp +++ b/networkdetector/devicemonitor.cpp @@ -2,6 +2,8 @@ #include "extern-plugininfo.h" +#include + DeviceMonitor::DeviceMonitor(const QString &macAddress, const QString &ipAddress, QObject *parent): QObject(parent) { @@ -36,13 +38,27 @@ void DeviceMonitor::lookupArpCache() void DeviceMonitor::ping() { // qCDebug(dcNetworkDetector()) << "Running:" << "ping" << "-c" << "1" << m_host->address(); - m_pingProcess->start("ping", {"-c", "1", m_host->address()}); + QNetworkInterface targetInterface; + foreach (const QNetworkInterface &interface, QNetworkInterface::allInterfaces()) { + foreach (const QNetworkAddressEntry &addressEntry, interface.addressEntries()) { + QHostAddress clientAddress(m_host->address()); + if (clientAddress.isInSubnet(addressEntry.ip(), addressEntry.prefixLength())) { + targetInterface = interface; + break; + } + } + } + if (!targetInterface.isValid()) { + qCWarning(dcNetworkDetector()) << "Could not find a suitable interface to ping for" << m_host->address(); + return; + } + m_pingProcess->start("arping", {"-I", targetInterface.name(), "-f", "-w", "5", m_host->address()}); } void DeviceMonitor::arpLookupFinished(int exitCode) { if (exitCode != 0) { - qWarning(dcNetworkDetector()) << "Error looking up ARP cache."; + qCWarning(dcNetworkDetector()) << "Error looking up ARP cache."; return; } @@ -60,7 +76,7 @@ void DeviceMonitor::arpLookupFinished(int exitCode) emit addressChanged(parts.first()); } if (parts.last() == "REACHABLE") { - qDebug(dcNetworkDetector()) << "Device" << m_host->macAddress() << "found in ARP cache and claims to be REACHABLE"; + qCDebug(dcNetworkDetector()) << "Device" << m_host->macAddress() << "found in ARP cache and claims to be REACHABLE"; m_host->seen(); if (!m_host->reachable()) { m_host->setReachable(true); @@ -80,8 +96,8 @@ void DeviceMonitor::arpLookupFinished(int exitCode) ping(); } - if (m_host->reachable() && m_host->lastSeenTime().addSecs(300) < QDateTime::currentDateTime()) { - qCDebug(dcNetworkDetector()) << "Could not reach device for > 5 mins. Marking it as gone." << m_host->address() << m_host->macAddress(); + if (m_host->reachable() && m_host->lastSeenTime().addSecs(20) < QDateTime::currentDateTime()) { + qCDebug(dcNetworkDetector()) << "Could not reach device for 20 seconds. Marking it as gone." << m_host->address() << m_host->macAddress(); m_host->setReachable(false); emit reachableChanged(false); } @@ -91,6 +107,7 @@ void DeviceMonitor::pingFinished(int exitCode) { if (exitCode == 0) { // we were able to ping the device + qCDebug(dcNetworkDetector()) << "Ping successful for" << m_host->macAddress() << m_host->address(); m_host->seen(); if (!m_host->reachable()) { m_host->setReachable(true); @@ -98,7 +115,7 @@ void DeviceMonitor::pingFinished(int exitCode) } emit seen(); } else { - qDebug(dcNetworkDetector()) << "Could not ping device" << m_host->macAddress() << m_host->address(); + qCDebug(dcNetworkDetector()) << "Could not ping device" << m_host->macAddress() << m_host->address(); } // read data to discard it from socket QString data = QString::fromLatin1(m_pingProcess->readAll()); diff --git a/networkdetector/devicepluginnetworkdetector.cpp b/networkdetector/devicepluginnetworkdetector.cpp index 4cada1ce..7556e7b0 100644 --- a/networkdetector/devicepluginnetworkdetector.cpp +++ b/networkdetector/devicepluginnetworkdetector.cpp @@ -142,9 +142,8 @@ void DevicePluginNetworkDetector::deviceReachableChanged(bool reachable) { DeviceMonitor *monitor = static_cast(sender()); Device *device = m_monitors.value(monitor); - if (device->stateValue(networkDeviceConnectedStateTypeId).toBool() != reachable) { - qCDebug(dcNetworkDetector()) << "Device" << device->paramValue(networkDeviceDeviceMacAddressParamTypeId).toString() << "reachable changed" << reachable; - device->setStateValue(networkDeviceConnectedStateTypeId, reachable); + if (device->stateValue(networkDeviceIsPresentStateTypeId).toBool() != reachable) { + qCDebug(dcNetworkDetector()) << "Device" << device->name() << device->paramValue(networkDeviceDeviceMacAddressParamTypeId).toString() << "reachable changed" << reachable; device->setStateValue(networkDeviceIsPresentStateTypeId, reachable); } } @@ -154,6 +153,7 @@ void DevicePluginNetworkDetector::deviceAddressChanged(const QString &address) DeviceMonitor *monitor = static_cast(sender()); Device *device = m_monitors.value(monitor); if (device->paramValue(networkDeviceDeviceAddressParamTypeId).toString() != address) { + qCDebug(dcNetworkDetector()) << "Device" << device->name() << device->paramValue(networkDeviceDeviceMacAddressParamTypeId).toString() << "changed IP address to" << address; device->setParamValue(networkDeviceDeviceAddressParamTypeId.toString(), address); } } diff --git a/networkdetector/devicepluginnetworkdetector.json b/networkdetector/devicepluginnetworkdetector.json index a8d303af..4768567a 100644 --- a/networkdetector/devicepluginnetworkdetector.json +++ b/networkdetector/devicepluginnetworkdetector.json @@ -17,7 +17,7 @@ "Device", "Sensor" ], - "interfaces": [ "connectable", "presencesensor" ], + "interfaces": [ "presencesensor" ], "primaryStateTypeId": "cb43e1b5-4f61-4538-bfa2-c33055c542cf", "createMethods": ["user", "discovery"], "paramTypes": [ @@ -39,15 +39,6 @@ "stateTypes": [ { "id": "cb43e1b5-4f61-4538-bfa2-c33055c542cf", - "name": "connected", - "displayName": "Device in network", - "displayNameEvent": "Device in network changed", - "type": "bool", - "defaultValue": false, - "cached": false - }, - { - "id": "0a38651c-418d-42b3-80f5-6e7adb6a25fc", "name": "isPresent", "displayName": "Device is present", "displayNameEvent": "Device is present changed", From 886ae142271c7a10e450f0b752e4e637aa301cbc Mon Sep 17 00:00:00 2001 From: Michael Zanetti Date: Mon, 31 Dec 2018 01:07:48 +0100 Subject: [PATCH 3/5] tune timeouts --- networkdetector/devicemonitor.cpp | 21 ++++++++++++------- .../devicepluginnetworkdetector.cpp | 1 + .../devicepluginnetworkdetector.json | 3 +-- 3 files changed, 16 insertions(+), 9 deletions(-) diff --git a/networkdetector/devicemonitor.cpp b/networkdetector/devicemonitor.cpp index 7c0eaed0..dfc54c6f 100644 --- a/networkdetector/devicemonitor.cpp +++ b/networkdetector/devicemonitor.cpp @@ -27,6 +27,10 @@ DeviceMonitor::~DeviceMonitor() void DeviceMonitor::update() { + if (m_pingProcess->state() != QProcess::NotRunning) { + qCDebug(dcNetworkDetector()) << "Previous ping still running for device" << m_host->address() << ". Not updating."; + return; + } lookupArpCache(); } @@ -50,9 +54,14 @@ void DeviceMonitor::ping() } if (!targetInterface.isValid()) { qCWarning(dcNetworkDetector()) << "Could not find a suitable interface to ping for" << m_host->address(); + if (m_host->reachable()) { + m_host->setReachable(false); + emit reachableChanged(false); + } return; } - m_pingProcess->start("arping", {"-I", targetInterface.name(), "-f", "-w", "5", m_host->address()}); + + m_pingProcess->start("arping", {"-I", targetInterface.name(), "-f", "-w", "90", m_host->address()}); } void DeviceMonitor::arpLookupFinished(int exitCode) @@ -95,12 +104,6 @@ void DeviceMonitor::arpLookupFinished(int exitCode) qCDebug(dcNetworkDetector()) << "Device" << m_host->macAddress() << "not found in ARP cache. Trying to ping it on" << m_host->address(); ping(); } - - if (m_host->reachable() && m_host->lastSeenTime().addSecs(20) < QDateTime::currentDateTime()) { - qCDebug(dcNetworkDetector()) << "Could not reach device for 20 seconds. Marking it as gone." << m_host->address() << m_host->macAddress(); - m_host->setReachable(false); - emit reachableChanged(false); - } } void DeviceMonitor::pingFinished(int exitCode) @@ -116,6 +119,10 @@ void DeviceMonitor::pingFinished(int exitCode) emit seen(); } else { qCDebug(dcNetworkDetector()) << "Could not ping device" << m_host->macAddress() << m_host->address(); + if (m_host->reachable()) { + m_host->setReachable(false); + emit reachableChanged(false); + } } // read data to discard it from socket QString data = QString::fromLatin1(m_pingProcess->readAll()); diff --git a/networkdetector/devicepluginnetworkdetector.cpp b/networkdetector/devicepluginnetworkdetector.cpp index 7556e7b0..605bba18 100644 --- a/networkdetector/devicepluginnetworkdetector.cpp +++ b/networkdetector/devicepluginnetworkdetector.cpp @@ -82,6 +82,7 @@ DeviceManager::DeviceSetupStatus DevicePluginNetworkDetector::setupDevice(Device connect(monitor, &DeviceMonitor::addressChanged, this, &DevicePluginNetworkDetector::deviceAddressChanged); connect(monitor, &DeviceMonitor::seen, this, &DevicePluginNetworkDetector::deviceSeen); m_monitors.insert(monitor, device); + monitor->update(); return DeviceManager::DeviceSetupStatusSuccess; } diff --git a/networkdetector/devicepluginnetworkdetector.json b/networkdetector/devicepluginnetworkdetector.json index 4768567a..074b3caa 100644 --- a/networkdetector/devicepluginnetworkdetector.json +++ b/networkdetector/devicepluginnetworkdetector.json @@ -43,8 +43,7 @@ "displayName": "Device is present", "displayNameEvent": "Device is present changed", "type": "bool", - "defaultValue": false, - "cached": false + "defaultValue": false }, { "id": "b51d54c9-cce1-43f0-a35d-52fc2d8d302c", From f2d4fa5255b6f579db90f1aa51c64a80af833cf8 Mon Sep 17 00:00:00 2001 From: Michael Zanetti Date: Wed, 9 Jan 2019 13:23:16 +0100 Subject: [PATCH 4/5] Handle duplicate stale arp cache entries better --- networkdetector/devicemonitor.cpp | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/networkdetector/devicemonitor.cpp b/networkdetector/devicemonitor.cpp index dfc54c6f..db0eba3c 100644 --- a/networkdetector/devicemonitor.cpp +++ b/networkdetector/devicemonitor.cpp @@ -41,7 +41,7 @@ void DeviceMonitor::lookupArpCache() void DeviceMonitor::ping() { -// qCDebug(dcNetworkDetector()) << "Running:" << "ping" << "-c" << "1" << m_host->address(); + qCDebug(dcNetworkDetector()) << "Sending ARP Ping to" << m_host->hostName() << m_host->macAddress() << m_host->address(); QNetworkInterface targetInterface; foreach (const QNetworkInterface &interface, QNetworkInterface::allInterfaces()) { foreach (const QNetworkAddressEntry &addressEntry, interface.addressEntries()) { @@ -73,35 +73,39 @@ void DeviceMonitor::arpLookupFinished(int exitCode) 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; - // Verify if IP address is still the same - if (parts.first() != m_host->address()) { - m_host->setAddress(parts.first()); - emit addressChanged(parts.first()); - } if (parts.last() == "REACHABLE") { qCDebug(dcNetworkDetector()) << "Device" << m_host->macAddress() << "found in ARP cache and claims to be REACHABLE"; - m_host->seen(); 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... try to ping it. - qCDebug(dcNetworkDetector()) << "Device" << m_host->macAddress() << "found in ARP cache but is marked as" << parts.last() << ". Trying to ping it on" << m_host->address(); - ping(); + // 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(); } - break; } } if (!found) { - qCDebug(dcNetworkDetector()) << "Device" << m_host->macAddress() << "not found in ARP cache. Trying to ping it on" << m_host->address(); + qCDebug(dcNetworkDetector()) << "Device" << m_host->macAddress() << "not found in ARP cache."; + ping(); + } else if (needsPing) { ping(); } } From a3a887fd7cd63cdbf681d3f81914c6c45a9c9650 Mon Sep 17 00:00:00 2001 From: Michael Zanetti Date: Thu, 10 Jan 2019 20:11:37 +0100 Subject: [PATCH 5/5] increate timeout and spam the log less --- networkdetector/devicemonitor.cpp | 2 +- networkdetector/devicepluginnetworkdetector.cpp | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/networkdetector/devicemonitor.cpp b/networkdetector/devicemonitor.cpp index db0eba3c..3c37976b 100644 --- a/networkdetector/devicemonitor.cpp +++ b/networkdetector/devicemonitor.cpp @@ -61,7 +61,7 @@ void DeviceMonitor::ping() return; } - m_pingProcess->start("arping", {"-I", targetInterface.name(), "-f", "-w", "90", m_host->address()}); + m_pingProcess->start("arping", {"-I", targetInterface.name(), "-f", "-w", "180", m_host->address()}); } void DeviceMonitor::arpLookupFinished(int exitCode) diff --git a/networkdetector/devicepluginnetworkdetector.cpp b/networkdetector/devicepluginnetworkdetector.cpp index 605bba18..b4733afa 100644 --- a/networkdetector/devicepluginnetworkdetector.cpp +++ b/networkdetector/devicepluginnetworkdetector.cpp @@ -163,5 +163,8 @@ void DevicePluginNetworkDetector::deviceSeen() { DeviceMonitor *monitor = static_cast(sender()); Device *device = m_monitors.value(monitor); - device->setStateValue(networkDeviceLastSeenTimeStateTypeId, QDateTime::currentDateTime().toTime_t()); + QDateTime oldLastSeen = QDateTime::fromTime_t(device->stateValue(networkDeviceLastSeenTimeStateTypeId).toInt()); + if (oldLastSeen.addSecs(60) < QDateTime::currentDateTime()) { + device->setStateValue(networkDeviceLastSeenTimeStateTypeId, QDateTime::currentDateTime().toTime_t()); + } }