mirror of
https://github.com/nymea/nymea-plugins.git
synced 2026-10-21 14:23:24 +02:00
Merge PR #70: Networkdetector: Implement the presencesensor interface
This commit is contained in:
commit
f5a7005c37
@ -2,6 +2,8 @@
|
|||||||
|
|
||||||
#include "extern-plugininfo.h"
|
#include "extern-plugininfo.h"
|
||||||
|
|
||||||
|
#include <QNetworkInterface>
|
||||||
|
|
||||||
DeviceMonitor::DeviceMonitor(const QString &macAddress, const QString &ipAddress, QObject *parent):
|
DeviceMonitor::DeviceMonitor(const QString &macAddress, const QString &ipAddress, QObject *parent):
|
||||||
QObject(parent)
|
QObject(parent)
|
||||||
{
|
{
|
||||||
@ -25,6 +27,10 @@ DeviceMonitor::~DeviceMonitor()
|
|||||||
|
|
||||||
void DeviceMonitor::update()
|
void DeviceMonitor::update()
|
||||||
{
|
{
|
||||||
|
if (m_pingProcess->state() != QProcess::NotRunning) {
|
||||||
|
qCDebug(dcNetworkDetector()) << "Previous ping still running for device" << m_host->address() << ". Not updating.";
|
||||||
|
return;
|
||||||
|
}
|
||||||
lookupArpCache();
|
lookupArpCache();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -35,54 +41,72 @@ void DeviceMonitor::lookupArpCache()
|
|||||||
|
|
||||||
void DeviceMonitor::ping()
|
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();
|
||||||
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();
|
||||||
|
if (m_host->reachable()) {
|
||||||
|
m_host->setReachable(false);
|
||||||
|
emit reachableChanged(false);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_pingProcess->start("arping", {"-I", targetInterface.name(), "-f", "-w", "180", m_host->address()});
|
||||||
}
|
}
|
||||||
|
|
||||||
void DeviceMonitor::arpLookupFinished(int exitCode)
|
void DeviceMonitor::arpLookupFinished(int exitCode)
|
||||||
{
|
{
|
||||||
if (exitCode != 0) {
|
if (exitCode != 0) {
|
||||||
qWarning(dcNetworkDetector()) << "Error looking up ARP cache.";
|
qCWarning(dcNetworkDetector()) << "Error looking up ARP cache.";
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString data = QString::fromLatin1(m_arpLookupProcess->readAll());
|
QString data = QString::fromLatin1(m_arpLookupProcess->readAll());
|
||||||
bool found = false;
|
bool found = false;
|
||||||
|
bool needsPing = true;
|
||||||
foreach (QString line, data.split('\n')) {
|
foreach (QString line, data.split('\n')) {
|
||||||
line.replace(QRegExp("[ ]{1,}"), " ");
|
line.replace(QRegExp("[ ]{1,}"), " ");
|
||||||
QStringList parts = line.split(" ");
|
QStringList parts = line.split(" ");
|
||||||
int lladdrIndex = parts.indexOf("lladdr");
|
int lladdrIndex = parts.indexOf("lladdr");
|
||||||
if (lladdrIndex >= 0 && parts.count() > lladdrIndex && parts.at(lladdrIndex+1).toLower() == m_host->macAddress().toLower()) {
|
if (lladdrIndex >= 0 && parts.count() > lladdrIndex && parts.at(lladdrIndex+1).toLower() == m_host->macAddress().toLower()) {
|
||||||
found = true;
|
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") {
|
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()) {
|
if (!m_host->reachable()) {
|
||||||
m_host->setReachable(true);
|
m_host->setReachable(true);
|
||||||
emit reachableChanged(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 {
|
} else {
|
||||||
// ARP claims the device to be stale... try to ping it.
|
// 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() << ". Trying to ping it on" << m_host->address();
|
qCDebug(dcNetworkDetector()) << "Device" << m_host->macAddress() << "found in ARP cache but is marked as" << parts.last();
|
||||||
ping();
|
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!found) {
|
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();
|
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();
|
|
||||||
m_host->setReachable(false);
|
|
||||||
emit reachableChanged(false);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -90,13 +114,19 @@ 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();
|
||||||
m_host->seen();
|
m_host->seen();
|
||||||
if (!m_host->reachable()) {
|
if (!m_host->reachable()) {
|
||||||
m_host->setReachable(true);
|
m_host->setReachable(true);
|
||||||
emit reachableChanged(true);
|
emit reachableChanged(true);
|
||||||
}
|
}
|
||||||
|
emit seen();
|
||||||
} else {
|
} 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();
|
||||||
|
if (m_host->reachable()) {
|
||||||
|
m_host->setReachable(false);
|
||||||
|
emit reachableChanged(false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// read data to discard it from socket
|
// read data to discard it from socket
|
||||||
QString data = QString::fromLatin1(m_pingProcess->readAll());
|
QString data = QString::fromLatin1(m_pingProcess->readAll());
|
||||||
|
|||||||
@ -19,6 +19,7 @@ public:
|
|||||||
signals:
|
signals:
|
||||||
void addressChanged(const QString &address);
|
void addressChanged(const QString &address);
|
||||||
void reachableChanged(bool reachable);
|
void reachableChanged(bool reachable);
|
||||||
|
void seen();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void lookupArpCache();
|
void lookupArpCache();
|
||||||
|
|||||||
@ -80,7 +80,9 @@ DeviceManager::DeviceSetupStatus DevicePluginNetworkDetector::setupDevice(Device
|
|||||||
DeviceMonitor *monitor = new DeviceMonitor(device->paramValue(networkDeviceDeviceMacAddressParamTypeId).toString(), device->paramValue(networkDeviceDeviceAddressParamTypeId).toString(), this);
|
DeviceMonitor *monitor = new DeviceMonitor(device->paramValue(networkDeviceDeviceMacAddressParamTypeId).toString(), device->paramValue(networkDeviceDeviceAddressParamTypeId).toString(), 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);
|
||||||
m_monitors.insert(monitor, device);
|
m_monitors.insert(monitor, device);
|
||||||
|
monitor->update();
|
||||||
|
|
||||||
return DeviceManager::DeviceSetupStatusSuccess;
|
return DeviceManager::DeviceSetupStatusSuccess;
|
||||||
}
|
}
|
||||||
@ -141,9 +143,9 @@ void DevicePluginNetworkDetector::deviceReachableChanged(bool reachable)
|
|||||||
{
|
{
|
||||||
DeviceMonitor *monitor = static_cast<DeviceMonitor*>(sender());
|
DeviceMonitor *monitor = static_cast<DeviceMonitor*>(sender());
|
||||||
Device *device = m_monitors.value(monitor);
|
Device *device = m_monitors.value(monitor);
|
||||||
if (device->stateValue(networkDeviceConnectedStateTypeId).toBool() != reachable) {
|
if (device->stateValue(networkDeviceIsPresentStateTypeId).toBool() != reachable) {
|
||||||
qCDebug(dcNetworkDetector()) << "Device" << device->paramValue(networkDeviceDeviceMacAddressParamTypeId).toString() << "reachable changed" << reachable;
|
qCDebug(dcNetworkDetector()) << "Device" << device->name() << device->paramValue(networkDeviceDeviceMacAddressParamTypeId).toString() << "reachable changed" << reachable;
|
||||||
device->setStateValue(networkDeviceConnectedStateTypeId, reachable);
|
device->setStateValue(networkDeviceIsPresentStateTypeId, reachable);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -152,6 +154,17 @@ void DevicePluginNetworkDetector::deviceAddressChanged(const QString &address)
|
|||||||
DeviceMonitor *monitor = static_cast<DeviceMonitor*>(sender());
|
DeviceMonitor *monitor = static_cast<DeviceMonitor*>(sender());
|
||||||
Device *device = m_monitors.value(monitor);
|
Device *device = m_monitors.value(monitor);
|
||||||
if (device->paramValue(networkDeviceDeviceAddressParamTypeId).toString() != address) {
|
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);
|
device->setParamValue(networkDeviceDeviceAddressParamTypeId.toString(), address);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DevicePluginNetworkDetector::deviceSeen()
|
||||||
|
{
|
||||||
|
DeviceMonitor *monitor = static_cast<DeviceMonitor*>(sender());
|
||||||
|
Device *device = m_monitors.value(monitor);
|
||||||
|
QDateTime oldLastSeen = QDateTime::fromTime_t(device->stateValue(networkDeviceLastSeenTimeStateTypeId).toInt());
|
||||||
|
if (oldLastSeen.addSecs(60) < QDateTime::currentDateTime()) {
|
||||||
|
device->setStateValue(networkDeviceLastSeenTimeStateTypeId, QDateTime::currentDateTime().toTime_t());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@ -57,6 +57,7 @@ private slots:
|
|||||||
|
|
||||||
void deviceReachableChanged(bool reachable);
|
void deviceReachableChanged(bool reachable);
|
||||||
void deviceAddressChanged(const QString &address);
|
void deviceAddressChanged(const QString &address);
|
||||||
|
void deviceSeen();
|
||||||
|
|
||||||
void onPluginTimer();
|
void onPluginTimer();
|
||||||
|
|
||||||
|
|||||||
@ -17,7 +17,7 @@
|
|||||||
"Device",
|
"Device",
|
||||||
"Sensor"
|
"Sensor"
|
||||||
],
|
],
|
||||||
"interfaces": ["connectable"],
|
"interfaces": [ "presencesensor" ],
|
||||||
"primaryStateTypeId": "cb43e1b5-4f61-4538-bfa2-c33055c542cf",
|
"primaryStateTypeId": "cb43e1b5-4f61-4538-bfa2-c33055c542cf",
|
||||||
"createMethods": ["user", "discovery"],
|
"createMethods": ["user", "discovery"],
|
||||||
"paramTypes": [
|
"paramTypes": [
|
||||||
@ -39,12 +39,20 @@
|
|||||||
"stateTypes": [
|
"stateTypes": [
|
||||||
{
|
{
|
||||||
"id": "cb43e1b5-4f61-4538-bfa2-c33055c542cf",
|
"id": "cb43e1b5-4f61-4538-bfa2-c33055c542cf",
|
||||||
"name": "connected",
|
"name": "isPresent",
|
||||||
"displayName": "Device in network",
|
"displayName": "Device is present",
|
||||||
"displayNameEvent": "Device in network changed",
|
"displayNameEvent": "Device is present changed",
|
||||||
"type": "bool",
|
"type": "bool",
|
||||||
"defaultValue": false,
|
"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
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user