diff --git a/libnymea-core/hardware/network/networkdevicediscoveryimpl.cpp b/libnymea-core/hardware/network/networkdevicediscoveryimpl.cpp index 60dbc1f5..f6f07472 100644 --- a/libnymea-core/hardware/network/networkdevicediscoveryimpl.cpp +++ b/libnymea-core/hardware/network/networkdevicediscoveryimpl.cpp @@ -1,6 +1,6 @@ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -* Copyright 2013 - 2022, nymea GmbH +* Copyright 2013 - 2024, nymea GmbH * Contact: contact@nymea.io * * This file is part of nymea. @@ -32,6 +32,7 @@ #include "nymeasettings.h" #include "loggingcategories.h" + #include #include @@ -134,13 +135,17 @@ NetworkDeviceDiscoveryReply *NetworkDeviceDiscoveryImpl::discover() connect(m_currentDiscoveryReply, &NetworkDeviceDiscoveryReplyImpl::finished, this, [this](){ // Finish all pending replies foreach (NetworkDeviceDiscoveryReplyImpl *reply, m_pendingDiscoveryReplies) { - // Sync all network device infos with all pending replies foreach (const NetworkDeviceInfo &info, m_currentDiscoveryReply->networkDeviceInfos()) { reply->addCompleteNetworkDeviceInfo(info); } } + // Update local cache right after a discovery finished + foreach (const NetworkDeviceInfo &info, m_currentDiscoveryReply->networkDeviceInfos()) { + updateCache(info); + } + // Delete the current reply before finishing the pending replies. // Just in case some one restarts a discovery on finished, a new internal // object should be created @@ -213,77 +218,144 @@ bool NetworkDeviceDiscoveryImpl::running() const return m_running; } -NetworkDeviceMonitor *NetworkDeviceDiscoveryImpl::registerMonitor(const MacAddress &macAddress) +// NetworkDeviceMonitor *NetworkDeviceDiscoveryImpl::registerMonitor(const MacAddress &macAddress) +// { +// if (macAddress.isNull()) { +// qCWarning(dcNetworkDeviceDiscovery()) << "Could not register monitor for invalid" << macAddress; +// return nullptr; +// } + +// // Make sure we create only one monitor per MAC and keep track how many user +// // have access to this monitor otherwise an unregister could cause a crash in +// // an other plugin plugin which might still need it +// if (m_monitors.contains(macAddress)) { +// m_monitorsReferenceCount[macAddress] += 1; +// qCInfo(dcNetworkDeviceDiscovery()) << "Register network device monitor for" << macAddress << "which already exists. Returning existing monitor having now" << m_monitorsReferenceCount[macAddress] << "references."; +// return m_monitors.value(macAddress); +// } + +// qCInfo(dcNetworkDeviceDiscovery()) << "Register new network device monitor for" << macAddress; + +// // Fill in cached information +// NetworkDeviceInfo info; +// if (m_networkInfoCache.contains(macAddress)) { +// info = m_networkInfoCache.value(macAddress); +// } else { +// info.setMacAddress(macAddress.toString()); +// } + +// NetworkDeviceMonitorImpl *monitor = new NetworkDeviceMonitorImpl(macAddress, this); +// monitor->setNetworkDeviceInfo(info); +// monitor->setLastSeen(m_lastSeen.value(macAddress, QDateTime())); +// m_monitors.insert(macAddress, monitor); +// m_monitorsReferenceCount[macAddress] = 1; + +// if (!available()) { +// qCWarning(dcNetworkDeviceDiscovery()) << "Registered monitor but the hardware resource is not available. The monitor will not work as expected" << monitor; +// return monitor; +// } + +// // Restart the monitor timer since we evaluate this one now +// m_monitorTimer->start(); + +// if (!monitor->networkDeviceInfo().isValid()) { +// qCDebug(dcNetworkDeviceDiscovery()) << "Adding network device monitor for unresolved mac address. Starting a discovery..."; +// NetworkDeviceDiscoveryReply *reply = discover(); +// connect(reply, &NetworkDeviceDiscoveryReply::finished, reply, &NetworkDeviceDiscoveryReply::deleteLater); +// } else { +// evaluateMonitor(monitor); +// } + +// qCDebug(dcNetworkDeviceDiscovery()) << "Registered successfully" << monitor; +// return monitor; +// } + +NetworkDeviceMonitor *NetworkDeviceDiscoveryImpl::registerMonitor(Thing *thing) { - if (macAddress.isNull()) { - qCWarning(dcNetworkDeviceDiscovery()) << "Could not register monitor for invalid" << macAddress; + if (!thing->thingClass().interfaces().contains("networkdevice")) { + qCWarning(dcNetworkDeviceDiscovery()) << "Cannot register network device monitor because the thing" + << thing << "does not implement the \"networkdevice\" interface."; return nullptr; } - // FIXME - return nullptr; + MacAddress macAddress(thing->paramValue("macAddress").toString()); + QString hostName = thing->paramValue("hostName").toString(); + QHostAddress address(thing->paramValue("address").toString()); - // // Make sure we create only one monitor per MAC and keep track how many user - // // have access to this monitor otherwise an unregister could cause a crash in - // // an other plugin plugin which might still need it - // if (m_monitors.contains(macAddress)) { - // m_monitorsReferenceCount[macAddress] += 1; - // qCInfo(dcNetworkDeviceDiscovery()) << "Register network device monitor for" << macAddress << "which already exists. Returning existing monitor having now" << m_monitorsReferenceCount[macAddress] << "references."; - // return m_monitors.value(macAddress); - // } + NetworkDeviceInfo::MonitorMode mode = NetworkDeviceInfo::MonitorModeMac; + if (macAddress.isNull()) { + if (!hostName.isEmpty()) { + mode = NetworkDeviceInfo::MonitorModeHostName; + } else { + if (address.isNull()) { + qCWarning(dcNetworkDeviceDiscovery()) << "Cannot register monitor for thing" << thing << + "because there are not enough information available." << + "At least one parameter from the networkdevice interface needs to be provided." << thing->params(); + return nullptr; + } else { + mode = NetworkDeviceInfo::MonitorModeIp; + } + } + } // else we use the MAC address mode - // qCInfo(dcNetworkDeviceDiscovery()) << "Register new network device monitor for" << macAddress; - - // // Fill in cached information - // NetworkDeviceInfo info; - // if (m_networkInfoCache.contains(macAddress)) { - // info = m_networkInfoCache.value(macAddress); - // } else { - // info.setMacAddress(macAddress.toString()); - // } - - // NetworkDeviceMonitorImpl *monitor = new NetworkDeviceMonitorImpl(macAddress, this); - // monitor->setNetworkDeviceInfo(info); - // monitor->setLastSeen(m_lastSeen.value(macAddress, QDateTime())); - // m_monitors.insert(macAddress, monitor); - // m_monitorsReferenceCount[macAddress] = 1; - - // if (!available()) { - // qCWarning(dcNetworkDeviceDiscovery()) << "Registered monitor but the hardware resource is not available. The monitor will not work as expected" << monitor; - // return monitor; - // } - - // // Restart the monitor timer since we evaluate this one now - // m_monitorTimer->start(); - - // if (!monitor->networkDeviceInfo().isValid()) { - // qCDebug(dcNetworkDeviceDiscovery()) << "Adding network device monitor for unresolved mac address. Starting a discovery..."; - // NetworkDeviceDiscoveryReply *reply = discover(); - // connect(reply, &NetworkDeviceDiscoveryReply::finished, reply, &NetworkDeviceDiscoveryReply::deleteLater); - // } else { - // evaluateMonitor(monitor); - // } - - // qCDebug(dcNetworkDeviceDiscovery()) << "Registered successfully" << monitor; - // return monitor; -} - -void NetworkDeviceDiscoveryImpl::unregisterMonitor(const MacAddress &macAddress) -{ - if (m_monitorsReferenceCount.contains(macAddress)) { - m_monitorsReferenceCount[macAddress] -= 1; - if (m_monitorsReferenceCount[macAddress] > 0) { - qCDebug(dcNetworkDeviceDiscovery()) << "Unregistered monitor for" << macAddress.toString() << "but keeping the monitor. There are still" << m_monitorsReferenceCount[macAddress] << "references to it."; - return; + // Check if we already have a monitor for these settings... + NetworkDeviceMonitorImpl *internalMonitor = nullptr; + for (QHash>::const_iterator iterator = m_monitors.cbegin(), + end = m_monitors.cend(); iterator != end; ++iterator) { + if (iterator.key()->address() == address && iterator.key()->macAddress() == macAddress && iterator.key()->hostName() == hostName) { + internalMonitor = iterator.key(); + break; } } - if (m_monitors.contains(macAddress)) { - NetworkDeviceMonitorImpl *monitor = m_monitors.take(macAddress); - qCInfo(dcNetworkDeviceDiscovery()) << "Unregister" << monitor; - monitor->deleteLater(); - m_monitorsReferenceCount.remove(macAddress); + if (internalMonitor) { + qCDebug(dcNetworkDeviceDiscovery()) << "Already have an internal monitor for this network device" << internalMonitor; + } else { + // Create a new monitor for the internal use + internalMonitor = new NetworkDeviceMonitorImpl(macAddress, hostName, address, this); } + + internalMonitor->setMonitorMode(mode); + + if (m_networkInfoCache.isEmpty()) { + qCDebug(dcNetworkDeviceDiscovery()) << "Cache is empty. Starting an internal discovery..."; + NetworkDeviceDiscoveryReply *reply = discover(); + connect(reply, &NetworkDeviceDiscoveryReply::finished, reply, &NetworkDeviceDiscoveryReply::deleteLater); + } + + // Find and set the network device info + for (int i = 0; i < m_networkInfoCache.count(); i++) { + const NetworkDeviceInfo networkDeviceInfo = m_networkInfoCache.at(i); + + switch (internalMonitor->monitorMode()) { + case NetworkDeviceInfo::MonitorModeMac: + // Search the unique mac address + if (networkDeviceInfo.macAddressInfos().hasMacAddress(internalMonitor->macAddress())) { + qCDebug(dcNetworkDeviceDiscovery()) << "MAC monitor:" << networkDeviceInfo; + internalMonitor->setNetworkDeviceInfo(networkDeviceInfo); + } + break; + case NetworkDeviceInfo::MonitorModeHostName: + // Search the unique mac address + if (networkDeviceInfo.hostName() == internalMonitor->hostName()) { + qCDebug(dcNetworkDeviceDiscovery()) << "Host name monitor:" << networkDeviceInfo; + internalMonitor->setNetworkDeviceInfo(networkDeviceInfo); + } + break; + case NetworkDeviceInfo::MonitorModeIp: + // Search the unique mac address + if (networkDeviceInfo.address() == internalMonitor->address()) { + qCDebug(dcNetworkDeviceDiscovery()) << "IP monitor:" << networkDeviceInfo; + internalMonitor->setNetworkDeviceInfo(networkDeviceInfo); + } + break; + } + } + + // Create a new plugin monitor object we are going to return... + NetworkDeviceMonitorImpl *pluginMonitor = createPluginMonitor(internalMonitor); + qCDebug(dcNetworkDeviceDiscovery()) << "Registered successfully" << pluginMonitor; + return pluginMonitor; } void NetworkDeviceDiscoveryImpl::unregisterMonitor(NetworkDeviceMonitor *networkDeviceMonitor) @@ -291,11 +363,7 @@ void NetworkDeviceDiscoveryImpl::unregisterMonitor(NetworkDeviceMonitor *network if (!networkDeviceMonitor) return; - if (!m_monitors.values().contains(qobject_cast(networkDeviceMonitor))) - return; - - // FIXME - //unregisterMonitor(MacAddress(networkDeviceMonitor->networkDeviceInfo().macAddress())); + cleanupPluginMonitor(qobject_cast(networkDeviceMonitor)); } PingReply *NetworkDeviceDiscoveryImpl::ping(const QHostAddress &address, uint retries) @@ -481,11 +549,11 @@ void NetworkDeviceDiscoveryImpl::watchPingReply(PingReply *reply) // } // Update any monitor - foreach (NetworkDeviceMonitorImpl *monitor, m_monitors.values()) { - if (monitor->networkDeviceInfo().address() == reply->targetHostAddress()) { - processMonitorPingResult(reply, monitor); - } - } + // foreach (NetworkDeviceMonitorImpl *monitor, m_monitors.values()) { + // if (monitor->networkDeviceInfo().address() == reply->targetHostAddress()) { + // processMonitorPingResult(reply, monitor); + // } + // } }); } @@ -503,36 +571,41 @@ void NetworkDeviceDiscoveryImpl::loadNetworkDeviceCache() if (cacheVersion == CACHE_VERSION) { m_cacheSettings->beginGroup("NetworkDeviceInfos"); - foreach (const QString &macAddress, m_cacheSettings->childGroups()) { - m_cacheSettings->beginGroup(macAddress); + foreach (const QString &addressString, m_cacheSettings->childGroups()) { - // MacAddress mac(macAddress); - // QDateTime lastSeen = QDateTime::fromMSecsSinceEpoch(m_cacheSettings->value("lastSeen").toLongLong()); + m_cacheSettings->beginGroup(addressString); - // // Remove the info from the cache if not seen fo the last 30 days... - // if (lastSeen.date().addDays(m_cacheCleanupPeriod) < now.date()) { - // qCDebug(dcNetworkDeviceDiscovery()) << "Removing network device cache entry since it did not show up within the last" << m_cacheCleanupPeriod << "days" << mac.toString(); - // m_cacheSettings->remove(""); - // m_cacheSettings->endGroup(); // mac address - // continue; - // } + QHostAddress address(addressString); + QDateTime lastSeen = QDateTime::fromMSecsSinceEpoch(m_cacheSettings->value("lastSeen").toLongLong()); - // NetworkDeviceInfo info(mac.toString()); - // info.setAddress(QHostAddress(m_cacheSettings->value("address").toString())); - // info.setHostName(m_cacheSettings->value("hostName").toString()); - // info.setMacAddressManufacturer(m_cacheSettings->value("manufacturer").toString()); - // info.setNetworkInterface(QNetworkInterface::interfaceFromName(m_cacheSettings->value("interface").toString())); + // Remove the info from the cache if not seen fo the last 30 days... + if (lastSeen.date().addDays(m_cacheCleanupPeriod) < now.date()) { + qCDebug(dcNetworkDeviceDiscovery()) << "Removing network device cache entry since it did not show up within the last" << m_cacheCleanupPeriod << "days" << address.toString(); + m_cacheSettings->remove(""); + m_cacheSettings->endGroup(); // mac address + continue; + } - // if (info.isValid() && info.isComplete()) { - // qCDebug(dcNetworkDeviceDiscovery()) << "Loaded cached" << info << "last seen" << lastSeen.toString(); - // m_networkInfoCache[mac] = info; - // m_lastSeen[mac] = lastSeen; - // } else { - // qCWarning(dcNetworkDeviceDiscovery()) << "Clean up invalid cached network device info from cache" << info; - // m_cacheSettings->remove(""); - // } + NetworkDeviceInfo info(address); + info.setHostName(m_cacheSettings->value("hostName").toString()); + info.setNetworkInterface(QNetworkInterface::interfaceFromName(m_cacheSettings->value("interface").toString())); - m_cacheSettings->endGroup(); // mac address + int size = m_cacheSettings->beginReadArray("mac"); + for (int i = 0; i < size; i++) { + m_cacheSettings->setArrayIndex(i); + MacAddress macAddress(m_cacheSettings->value("mac").toString()); + QString vendor = m_cacheSettings->value("vendor").toString(); + info.addMacAddress(macAddress, vendor); + // Cache the mac information for less DB access + if (!macAddress.isNull() && !vendor.isEmpty()) { + m_macVendorCache[macAddress] = vendor; + } + } + m_cacheSettings->endArray(); + m_cacheSettings->endGroup(); // address + qCDebug(dcNetworkDeviceDiscovery()) << "Loaded cached" << info << "last seen" << lastSeen.toString(); + m_networkInfoCache.append(info); + m_lastSeen[info.address()] = lastSeen; } m_cacheSettings->endGroup(); // NetworkDeviceInfos @@ -566,35 +639,56 @@ void NetworkDeviceDiscoveryImpl::removeFromNetworkDeviceCache(const MacAddress & // m_cacheSettings->sync(); } +void NetworkDeviceDiscoveryImpl::removeFromNetworkDeviceCache(const QHostAddress &address) +{ + if (address.isNull()) + return; + + m_networkInfoCache.removeHostAddress(address); + m_lastSeen.remove(address); + m_cacheSettings->beginGroup("NetworkDeviceInfos"); + m_cacheSettings->beginGroup(address.toString()); + m_cacheSettings->remove(""); + m_cacheSettings->endGroup(); // address + m_cacheSettings->endGroup(); // NetworkDeviceInfos + m_cacheSettings->sync(); +} + void NetworkDeviceDiscoveryImpl::saveNetworkDeviceCache(const NetworkDeviceInfo &deviceInfo) { if (!deviceInfo.isValid() || !deviceInfo.isComplete()) return; - // m_cacheSettings->beginGroup("NetworkDeviceInfos"); - // m_cacheSettings->beginGroup(deviceInfo.macAddress()); - // m_cacheSettings->setValue("address", deviceInfo.address().toString()); - // m_cacheSettings->setValue("hostName", deviceInfo.hostName()); - // m_cacheSettings->setValue("manufacturer", deviceInfo.macAddressManufacturer()); - // m_cacheSettings->setValue("interface", deviceInfo.networkInterface().name()); - // m_cacheSettings->setValue("lastSeen", convertMinuteBased(m_lastSeen.value(MacAddress(deviceInfo.macAddress()))).toMSecsSinceEpoch()); - // m_cacheSettings->endGroup(); // mac address - // m_cacheSettings->endGroup(); // NetworkDeviceInfos - // m_cacheSettings->sync(); + m_cacheSettings->beginGroup("NetworkDeviceInfos"); + m_cacheSettings->beginGroup(deviceInfo.address().toString()); + m_cacheSettings->setValue("hostName", deviceInfo.hostName()); + m_cacheSettings->setValue("interface", deviceInfo.networkInterface().name()); + m_cacheSettings->setValue("lastSeen", convertMinuteBased(m_lastSeen.value(deviceInfo.address())).toMSecsSinceEpoch()); + + if (!deviceInfo.macAddressInfos().isEmpty()){ + m_cacheSettings->beginWriteArray("mac"); + for (int i = 0; i < deviceInfo.macAddressInfos().size(); i++) { + m_cacheSettings->setArrayIndex(i); + m_cacheSettings->setValue("mac", deviceInfo.macAddressInfos().at(i).macAddress().toString()); + m_cacheSettings->setValue("vendor", deviceInfo.macAddressInfos().at(i).vendorName()); + } + m_cacheSettings->endArray(); // mac + } + + m_cacheSettings->endGroup(); // address + m_cacheSettings->endGroup(); // NetworkDeviceInfos + m_cacheSettings->sync(); } void NetworkDeviceDiscoveryImpl::updateCache(const NetworkDeviceInfo &deviceInfo) { - // MacAddress macAddress(deviceInfo.macAddress()); - // if (macAddress.isNull()) - // return; - - // FIXME - // if (m_monitors.contains(macAddress)) { - // NetworkDeviceMonitorImpl *monitor = m_monitors.value(macAddress); - // monitor->setNetworkDeviceInfo(deviceInfo); - // } - + // Update monitors + foreach (NetworkDeviceMonitorImpl *monitor, m_monitors.keys()) { + if (monitor->isMyNetworkDeviceInfo(deviceInfo)) { + monitor->setNetworkDeviceInfo(deviceInfo); + break; + } + } // Save only if changed int index = m_networkInfoCache.indexFromHostAddress(deviceInfo.address()); @@ -613,8 +707,9 @@ void NetworkDeviceDiscoveryImpl::updateCache(const NetworkDeviceInfo &deviceInfo void NetworkDeviceDiscoveryImpl::evaluateMonitor(NetworkDeviceMonitorImpl *monitor) { - if (!monitor->networkDeviceInfo().isValid()) - return; + // if (!monitor->networkDeviceInfo().isValid()) + // return; + if (monitor->currentPingReply()) return; @@ -673,7 +768,7 @@ void NetworkDeviceDiscoveryImpl::evaluateMonitor(NetworkDeviceMonitorImpl *monit void NetworkDeviceDiscoveryImpl::processArpTraffic(const QNetworkInterface &interface, const QHostAddress &address, const MacAddress &macAddress) { QDateTime now = QDateTime::currentDateTime(); - m_lastSeen[macAddress] = now; + // m_lastSeen[macAddress] = now; // FIXME @@ -775,6 +870,57 @@ QDateTime NetworkDeviceDiscoveryImpl::convertMinuteBased(const QDateTime &dateTi return dateTimeToConvert; } +NetworkDeviceMonitorImpl *NetworkDeviceDiscoveryImpl::createPluginMonitor(NetworkDeviceMonitorImpl *internalMonitor) +{ + NetworkDeviceMonitorImpl *pluginMonitor = new NetworkDeviceMonitorImpl(internalMonitor->macAddress(), internalMonitor->hostName(), internalMonitor->address(), this); + pluginMonitor->setNetworkDeviceInfo(internalMonitor->networkDeviceInfo()); + pluginMonitor->setMonitorMode(internalMonitor->monitorMode()); + pluginMonitor->setLastSeen(internalMonitor->lastSeen()); + pluginMonitor->setLastConnectionAttempt(internalMonitor->lastConnectionAttempt()); + pluginMonitor->setPingRetries(internalMonitor->pingRetries()); + pluginMonitor->setReachable(internalMonitor->reachable()); + + // internal monitor --> plugin monitor + connect(internalMonitor, &NetworkDeviceMonitorImpl::reachableChanged, pluginMonitor, [pluginMonitor](bool reachable){ + pluginMonitor->setReachable(reachable); + }); + connect(internalMonitor, &NetworkDeviceMonitorImpl::lastSeenChanged, pluginMonitor, [pluginMonitor](const QDateTime &lastSeen){ + pluginMonitor->setLastSeen(lastSeen); + }); + connect(internalMonitor, &NetworkDeviceMonitorImpl::networkDeviceInfoChanged, pluginMonitor, [pluginMonitor](const NetworkDeviceInfo &networkDeviceInfo){ + pluginMonitor->setNetworkDeviceInfo(networkDeviceInfo); + }); + + // plugin monitor --> internal monitor + connect(pluginMonitor, &NetworkDeviceMonitorImpl::pingRetriesChanged, internalMonitor, [internalMonitor](uint pingRetries){ + internalMonitor->setPingRetries(pingRetries); + }); + + // In case the plugin user is deleting the monitor object, we need to clean up here and check if we can remove the internal monitor + connect(pluginMonitor, &NetworkDeviceDiscoveryImpl::destroyed, this, [this, pluginMonitor](QObject *) { + cleanupPluginMonitor(pluginMonitor); + }); + + return pluginMonitor; +} + +void NetworkDeviceDiscoveryImpl::cleanupPluginMonitor(NetworkDeviceMonitorImpl *pluginMonitor) +{ + qCDebug(dcNetworkDeviceDiscovery()) << "Unregister plugin monitor" << pluginMonitor; + foreach (NetworkDeviceMonitorImpl *internalMonitor, m_monitors.keys()) { + if (m_monitors.value(internalMonitor).contains(pluginMonitor)) { + m_monitors[internalMonitor].removeAll(pluginMonitor); + + if (m_monitors.value(internalMonitor).isEmpty()) { + qCDebug(dcNetworkDeviceDiscovery()) << "No monitor registered for this network device any more. Unregister internal monitor" << internalMonitor; + // Last refference for this monitor, nobody need this any more. Clean up... + m_monitors.remove(internalMonitor); + internalMonitor->deleteLater(); + } + } + } +} + void NetworkDeviceDiscoveryImpl::onArpResponseReceived(const QNetworkInterface &interface, const QHostAddress &address, const MacAddress &macAddress) { // Ignore ARP from zero mac @@ -802,11 +948,11 @@ void NetworkDeviceDiscoveryImpl::onArpRequstReceived(const QNetworkInterface &in void NetworkDeviceDiscoveryImpl::evaluateMonitors() { bool monitorRequiresRediscovery = false; - foreach (NetworkDeviceMonitorImpl *monitor, m_monitors) { + foreach (NetworkDeviceMonitorImpl *monitor, m_monitors.keys()) { evaluateMonitor(monitor); // Check if there is any monitor which has not be seen since - if (!monitor->reachable() && monitor->lastConnectionAttempt().isValid() && longerAgoThan(monitor->lastSeen(), m_monitorInterval)) { + if (!monitor->reachable() /*&& monitor->lastConnectionAttempt().isValid()*/ && longerAgoThan(monitor->lastSeen(), m_monitorInterval)) { monitorRequiresRediscovery = true; } } @@ -817,20 +963,20 @@ void NetworkDeviceDiscoveryImpl::evaluateMonitors() connect(reply, &NetworkDeviceDiscoveryReply::finished, reply, &NetworkDeviceDiscoveryReply::deleteLater); } - // Do some cache housekeeping if required - if (m_lastCacheHousekeeping.addDays(1) < QDateTime::currentDateTime()) { - qCInfo(dcNetworkDeviceDiscovery()) << "Starting cache housekeeping since it is more than one day since the last clanup..."; - QDateTime now = QDateTime::currentDateTime(); - foreach (const MacAddress &mac, m_lastSeen.keys()) { - // Remove the info from the cache if not seen fo the last 30 days... - if (m_lastSeen.value(mac).date().addDays(m_cacheCleanupPeriod) < QDateTime::currentDateTime().date()) { - qCDebug(dcNetworkDeviceDiscovery()) << "Removing network device cache entry since it did not show up within the last" << m_cacheCleanupPeriod << "days" << mac.toString(); - removeFromNetworkDeviceCache(mac); - } - } - - m_lastCacheHousekeeping = now; - } + // FIXME + // // Do some cache housekeeping if required + // if (m_lastCacheHousekeeping.addDays(1) < QDateTime::currentDateTime()) { + // qCInfo(dcNetworkDeviceDiscovery()) << "Starting cache housekeeping since it is more than one day since the last clanup..."; + // QDateTime now = QDateTime::currentDateTime(); + // foreach (const MacAddress &mac, m_lastSeen.keys()) { + // // Remove the info from the cache if not seen fo the last 30 days... + // if (m_lastSeen.value(mac).date().addDays(m_cacheCleanupPeriod) < QDateTime::currentDateTime().date()) { + // qCDebug(dcNetworkDeviceDiscovery()) << "Removing network device cache entry since it did not show up within the last" << m_cacheCleanupPeriod << "days" << mac.toString(); + // removeFromNetworkDeviceCache(mac); + // } + // } + // m_lastCacheHousekeeping = now; + // } } void NetworkDeviceDiscoveryImpl::finishDiscovery() diff --git a/libnymea-core/hardware/network/networkdevicediscoveryimpl.h b/libnymea-core/hardware/network/networkdevicediscoveryimpl.h index 859eb102..30c41ea3 100644 --- a/libnymea-core/hardware/network/networkdevicediscoveryimpl.h +++ b/libnymea-core/hardware/network/networkdevicediscoveryimpl.h @@ -1,6 +1,6 @@ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -* Copyright 2013 - 2022, nymea GmbH +* Copyright 2013 - 2024, nymea GmbH * Contact: contact@nymea.io * * This file is part of nymea. @@ -31,10 +31,11 @@ #ifndef NETWORKDEVICEDISCOVERYIMPL_H #define NETWORKDEVICEDISCOVERYIMPL_H +#include #include #include -#include #include +#include #include #include @@ -66,9 +67,7 @@ public: NetworkDeviceDiscoveryReply *discover() override; - NetworkDeviceMonitor *registerMonitor(const MacAddress &macAddress) override; - - void unregisterMonitor(const MacAddress &macAddress) override; + NetworkDeviceMonitor *registerMonitor(Thing *thing) override; void unregisterMonitor(NetworkDeviceMonitor *networkDeviceMonitor) override; PingReply *ping(const QHostAddress &address, uint retries = 3) override; @@ -94,6 +93,7 @@ private: MacAddressDatabase *m_macAddressDatabase = nullptr; ArpSocket *m_arpSocket = nullptr; Ping *m_ping = nullptr; + bool m_enabled = true; bool m_running = false; @@ -112,9 +112,8 @@ private: QList m_runningMacDatabaseReplies; QList m_runningPingReplies; - QHash m_monitors; - QHash m_monitorsReferenceCount; - QHash m_lastSeen; + QHash> m_monitors; + QHash m_lastSeen; QHash m_macVendorCache; @@ -131,6 +130,7 @@ private: void loadNetworkDeviceCache(); void removeFromNetworkDeviceCache(const MacAddress &macAddress); + void removeFromNetworkDeviceCache(const QHostAddress &address); void saveNetworkDeviceCache(const NetworkDeviceInfo &deviceInfo); void updateCache(const NetworkDeviceInfo &deviceInfo); @@ -142,6 +142,9 @@ private: bool longerAgoThan(const QDateTime &dateTime, uint minutes); QDateTime convertMinuteBased(const QDateTime &dateTime = QDateTime()); + NetworkDeviceMonitorImpl *createPluginMonitor(NetworkDeviceMonitorImpl *internalMonitor); + void cleanupPluginMonitor(NetworkDeviceMonitorImpl *pluginMonitor); + private slots: void onArpResponseReceived(const QNetworkInterface &interface, const QHostAddress &address, const MacAddress &macAddress); void onArpRequstReceived(const QNetworkInterface &interface, const QHostAddress &address, const MacAddress &macAddress); diff --git a/libnymea-core/hardware/network/networkdevicediscoveryreplyimpl.cpp b/libnymea-core/hardware/network/networkdevicediscoveryreplyimpl.cpp index 453b2b12..4192ecd3 100644 --- a/libnymea-core/hardware/network/networkdevicediscoveryreplyimpl.cpp +++ b/libnymea-core/hardware/network/networkdevicediscoveryreplyimpl.cpp @@ -62,16 +62,12 @@ void NetworkDeviceDiscoveryReplyImpl::setFinished(bool finished) void NetworkDeviceDiscoveryReplyImpl::processPingResponse(const QHostAddress &address, const QString &hostName) { if (m_networkDeviceCache.contains(address)) { - // Update existing hostname... m_networkDeviceCache[address].setHostName(hostName); - evaluateMonitorMode(address); } else { - // Adding new host... NetworkDeviceInfo info; info.setAddress(address); info.setHostName(hostName); m_networkDeviceCache.insert(address, info); - evaluateMonitorMode(address); // First time seeing this host address emit hostAddressDiscovered(address); @@ -93,8 +89,6 @@ void NetworkDeviceDiscoveryReplyImpl::processArpResponse(const QNetworkInterface // First time seeing this host address emit hostAddressDiscovered(address); } - - evaluateMonitorMode(address); } void NetworkDeviceDiscoveryReplyImpl::processMacManufacturer(const MacAddress &macAddress, const QString &manufacturer) @@ -105,7 +99,6 @@ void NetworkDeviceDiscoveryReplyImpl::processMacManufacturer(const MacAddress &m foreach (const NetworkDeviceInfo &info, m_networkDeviceCache) { if (info.macAddressInfos().hasMacAddress(macAddress)) { m_networkDeviceCache[info.address()].addMacAddress(macAddress, manufacturer); - evaluateMonitorMode(info.address()); } } } @@ -128,11 +121,12 @@ void NetworkDeviceDiscoveryReplyImpl::processDiscoveryFinished() qCDebug(dcNetworkDeviceDiscovery()) << "Adding incomplete" << info << "to the final result:" << info.incompleteProperties(); m_networkDeviceCache[address].forceComplete(); - - evaluateMonitorMode(address); - m_networkDeviceInfos.append(m_networkDeviceCache.value(address)); + m_networkDeviceInfos.append(m_networkDeviceCache.take(address)); } + // Evaluate overall monitor mode... + evaluateMonitorMode(); + // Done, lets sort the result and inform m_networkDeviceInfos.sortNetworkDevices(); @@ -159,55 +153,72 @@ void NetworkDeviceDiscoveryReplyImpl::addCompleteNetworkDeviceInfo(const Network m_networkDeviceInfos.append(networkDeviceInfo); } -void NetworkDeviceDiscoveryReplyImpl::evaluateMonitorMode(const QHostAddress &address) +void NetworkDeviceDiscoveryReplyImpl::evaluateMonitorMode() { - qCDebug(dcNetworkDeviceDiscovery()) << "MonitorMode: Evaluating monitor mode for host" << address.toString(); + for (int i = 0; i < m_networkDeviceInfos.size(); i++) { - if (m_networkDeviceCache.value(address).macAddressInfos().isEmpty()) { - // Not discovered yet, or this is a virtual host like VPN - if (m_networkDeviceCache.value(address).hostName().isEmpty()) { - m_networkDeviceCache[address].setMonitorMode(NetworkDeviceInfo::MonitorModeIp); - qCDebug(dcNetworkDeviceDiscovery()) << "MonitorMode: No MAC address and no hostname, using IP only"; - } else { - qCDebug(dcNetworkDeviceDiscovery()) << "MonitorMode: No MAC address, but we have a hostname."; - m_networkDeviceCache[address].setMonitorMode(NetworkDeviceInfo::MonitorModeHostname); - } + const NetworkDeviceInfo info = m_networkDeviceInfos.at(i); + qCDebug(dcNetworkDeviceDiscovery()) << "MonitorMode: Evaluating host" << info.address().toString(); - } else { - // We have at least one mac address, check if there are other network devices with this MAC or if we have multiple MAC addresses - if (m_networkDeviceCache.value(address).macAddressInfos().count() == 1) { + NetworkDeviceInfo::MonitorMode mode = NetworkDeviceInfo::MonitorModeMac; + + if (info.macAddressInfos().isEmpty()) { + + // No MAC address found, no ARP for this host, probably a VPN client + if (info.hostName().isEmpty()) { + qCDebug(dcNetworkDeviceDiscovery()) << "MonitorMode: --> No MAC address and no host name, using MonitorModeIp"; + mode = NetworkDeviceInfo::MonitorModeIp; + } else { + qCDebug(dcNetworkDeviceDiscovery()) << "MonitorMode: --> No MAC address, but we have a host name, suing MonitorModeHostName"; + mode = NetworkDeviceInfo::MonitorModeHostName; + } + + } else if (info.macAddressInfos().size() == 1) { + + // Single mac address for this host.. + MacAddress macAddress = info.macAddressInfos().constFirst().macAddress(); + bool macAddressIsUnique = true; - bool uniqueMac = true; // Check if this mac is unique - foreach (const NetworkDeviceInfo &info, m_networkDeviceCache) { - if (info.address() == address) + foreach (const NetworkDeviceInfo &networkDeviceInfo, m_networkDeviceInfos) { + + // Skip our self... + if (networkDeviceInfo.address() == info.address()) continue; - if (info.macAddressInfos().hasMacAddress(m_networkDeviceCache.value(address).macAddressInfos().first().macAddress())) { - uniqueMac = false; + if (networkDeviceInfo.macAddressInfos().hasMacAddress(macAddress)) { + macAddressIsUnique = false; break; } } - if (!uniqueMac) { - if (m_networkDeviceCache.value(address).hostName().isEmpty()) { - m_networkDeviceCache[address].setMonitorMode(NetworkDeviceInfo::MonitorModeIp); - qCDebug(dcNetworkDeviceDiscovery()) << "MonitorMode: The MAC address of" << address.toString() << "is not unique in this network and no hostname available, using IP only"; + if (!macAddressIsUnique) { + if (info.hostName().isEmpty()) { + qCDebug(dcNetworkDeviceDiscovery()) << "MonitorMode: --> the MAC address of" << info.address().toString() << "is not unique in this network and no host name available, usgin MonitorModeIp"; + mode = NetworkDeviceInfo::MonitorModeIp; } else { - qCDebug(dcNetworkDeviceDiscovery()) << "MonitorMode: The MAC address of" << address.toString() << "is not unique in this network but we have a hostname"; - m_networkDeviceCache[address].setMonitorMode(NetworkDeviceInfo::MonitorModeHostname); + qCDebug(dcNetworkDeviceDiscovery()) << "MonitorMode: --> the MAC address of" << info.address().toString() << "is not unique in this network but we have a host name, usgin MonitorModeHostName"; + mode = NetworkDeviceInfo::MonitorModeHostName; } - } - } else { - // Multiple MAC addresses - if (m_networkDeviceCache.value(address).hostName().isEmpty()) { - m_networkDeviceCache[address].setMonitorMode(NetworkDeviceInfo::MonitorModeIp); - qCDebug(dcNetworkDeviceDiscovery()) << "MonitorMode: Multiple MAC addresses and no hostname, using IP only"; } else { - qCDebug(dcNetworkDeviceDiscovery()) << "MonitorMode: Multiple MAC addresses, but we have a hostname."; - m_networkDeviceCache[address].setMonitorMode(NetworkDeviceInfo::MonitorModeHostname); + qCDebug(dcNetworkDeviceDiscovery()) << "MonitorMode: --> the MAC address of" << info.address().toString() << "is unique in this network, usgin MonitorModeMac"; + mode = NetworkDeviceInfo::MonitorModeMac; + } + + } else if (info.macAddressInfos().size() > 1) { + + // Multiple MAC addresses + if (info.hostName().isEmpty()) { + qCDebug(dcNetworkDeviceDiscovery()) << "MonitorMode: --> multiple MAC addresses and no host name, usgin MonitorModeIp"; + mode = NetworkDeviceInfo::MonitorModeIp; + } else { + qCDebug(dcNetworkDeviceDiscovery()) << "MonitorMode: --> multiple MAC addresses, but we have a host name, usgin MonitorModeHostName"; + mode = NetworkDeviceInfo::MonitorModeHostName; } } + + m_networkDeviceInfos[i].setMonitorMode(mode); + qCDebug(dcNetworkDeviceDiscovery()) << "MonitorMode: --> Final" << m_networkDeviceInfos.at(i); } } diff --git a/libnymea-core/hardware/network/networkdevicediscoveryreplyimpl.h b/libnymea-core/hardware/network/networkdevicediscoveryreplyimpl.h index c41f2922..162ae6d9 100644 --- a/libnymea-core/hardware/network/networkdevicediscoveryreplyimpl.h +++ b/libnymea-core/hardware/network/networkdevicediscoveryreplyimpl.h @@ -71,7 +71,7 @@ private: NetworkDeviceInfos m_networkDeviceInfos; - void evaluateMonitorMode(const QHostAddress &address); + void evaluateMonitorMode(); }; } diff --git a/libnymea-core/hardware/network/networkdevicemonitorimpl.cpp b/libnymea-core/hardware/network/networkdevicemonitorimpl.cpp index 2bc0b19a..347d9a74 100644 --- a/libnymea-core/hardware/network/networkdevicemonitorimpl.cpp +++ b/libnymea-core/hardware/network/networkdevicemonitorimpl.cpp @@ -1,6 +1,6 @@ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -* Copyright 2013 - 2022, nymea GmbH +* Copyright 2013 - 2024, nymea GmbH * Contact: contact@nymea.io * * This file is part of nymea. @@ -35,9 +35,11 @@ Q_DECLARE_LOGGING_CATEGORY(dcNetworkDeviceDiscovery) namespace nymeaserver { -NetworkDeviceMonitorImpl::NetworkDeviceMonitorImpl(const MacAddress &macAddress, QObject *parent) : - NetworkDeviceMonitor(parent), - m_macAddress(macAddress) +NetworkDeviceMonitorImpl::NetworkDeviceMonitorImpl(const MacAddress &macAddress, const QString &hostName, const QHostAddress &address, QObject *parent) : + NetworkDeviceMonitor{parent}, + m_macAddress{macAddress}, + m_hostName{hostName}, + m_address{address} { } @@ -54,6 +56,26 @@ MacAddress NetworkDeviceMonitorImpl::macAddress() const return m_macAddress; } +QString NetworkDeviceMonitorImpl::hostName() const +{ + return m_hostName; +} + +QHostAddress NetworkDeviceMonitorImpl::address() const +{ + return m_address; +} + +NetworkDeviceInfo::MonitorMode NetworkDeviceMonitorImpl::monitorMode() const +{ + return m_monitorMode; +} + +void NetworkDeviceMonitorImpl::setMonitorMode(NetworkDeviceInfo::MonitorMode monitorMode) +{ + m_monitorMode = monitorMode; +} + NetworkDeviceInfo NetworkDeviceMonitorImpl::networkDeviceInfo() const { return m_networkDeviceInfo; @@ -127,4 +149,37 @@ void NetworkDeviceMonitorImpl::setLastConnectionAttempt(const QDateTime &lastCon m_lastConnectionAttempt = lastConnectionAttempt; } +bool NetworkDeviceMonitorImpl::isMyNetworkDeviceInfo(const NetworkDeviceInfo &networkDeviceInfo) const +{ + bool myNetworkDevice = false; + switch (m_monitorMode) { + case NetworkDeviceInfo::MonitorModeMac: + if (!m_macAddress.isNull() && networkDeviceInfo.macAddressInfos().count() == 1 && networkDeviceInfo.macAddressInfos().hasMacAddress(m_macAddress)) + myNetworkDevice = true; + + break; + case NetworkDeviceInfo::MonitorModeHostName: + if (!m_hostName.isEmpty() && networkDeviceInfo.hostName() == m_hostName) + myNetworkDevice = true; + + break; + case NetworkDeviceInfo::MonitorModeIp: + if (!m_address.isNull() && networkDeviceInfo.address() == m_address) + myNetworkDevice = true; + + break; + } + return myNetworkDevice; +} + +bool NetworkDeviceMonitorImpl::operator==(NetworkDeviceMonitorImpl *other) const +{ + return m_macAddress == other->macAddress() && m_hostName == other->hostName() && m_address == other->address(); +} + +bool NetworkDeviceMonitorImpl::operator!=(NetworkDeviceMonitorImpl *other) const +{ + return !operator==(other); +} + } diff --git a/libnymea-core/hardware/network/networkdevicemonitorimpl.h b/libnymea-core/hardware/network/networkdevicemonitorimpl.h index e438d2d7..6858bd0d 100644 --- a/libnymea-core/hardware/network/networkdevicemonitorimpl.h +++ b/libnymea-core/hardware/network/networkdevicemonitorimpl.h @@ -1,6 +1,6 @@ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -* Copyright 2013 - 2022, nymea GmbH +* Copyright 2013 - 2024, nymea GmbH * Contact: contact@nymea.io * * This file is part of nymea. @@ -34,8 +34,8 @@ #include #include -#include "network/networkdevicemonitor.h" #include "network/pingreply.h" +#include "network/networkdevicemonitor.h" namespace nymeaserver { @@ -44,10 +44,16 @@ class NetworkDeviceMonitorImpl : public NetworkDeviceMonitor Q_OBJECT public: - explicit NetworkDeviceMonitorImpl(const MacAddress &macAddress, QObject *parent = nullptr); + explicit NetworkDeviceMonitorImpl(const MacAddress &macAddress, const QString &hostName, const QHostAddress &address, QObject *parent = nullptr); ~NetworkDeviceMonitorImpl() override; + // Properties from the thing MacAddress macAddress() const override; + QString hostName() const override; + QHostAddress address() const override; + + NetworkDeviceInfo::MonitorMode monitorMode() const override; + void setMonitorMode(NetworkDeviceInfo::MonitorMode monitorMode); NetworkDeviceInfo networkDeviceInfo() const override; void setNetworkDeviceInfo(const NetworkDeviceInfo &networkDeviceInfo); @@ -67,14 +73,25 @@ public: QDateTime lastConnectionAttempt() const; void setLastConnectionAttempt(const QDateTime &lastConnectionAttempt); + bool isMyNetworkDeviceInfo(const NetworkDeviceInfo &networkDeviceInfo) const; + + bool operator==(NetworkDeviceMonitorImpl *other) const; + bool operator!=(NetworkDeviceMonitorImpl *other) const; private: - NetworkDeviceInfo m_networkDeviceInfo; MacAddress m_macAddress; + QString m_hostName; + QHostAddress m_address; + + NetworkDeviceInfo::MonitorMode m_monitorMode = NetworkDeviceInfo::MonitorModeMac; + + NetworkDeviceInfo m_networkDeviceInfo; + bool m_reachable = false; QDateTime m_lastSeen; QDateTime m_lastConnectionAttempt; uint m_pingRetries = 5; + PingReply *m_currentPingReply = nullptr; }; diff --git a/libnymea/network/macaddressinfos.cpp b/libnymea/network/macaddressinfos.cpp index 8bd171e6..938ee016 100644 --- a/libnymea/network/macaddressinfos.cpp +++ b/libnymea/network/macaddressinfos.cpp @@ -49,7 +49,7 @@ int MacAddressInfos::indexFromMacAddress(const QString &macAddress) int MacAddressInfos::indexFromMacAddress(const MacAddress &macAddress) { for (int i = 0; i < size(); i++) { - if (MacAddress(at(i).macAddress()) == macAddress) { + if (at(i).macAddress() == macAddress) { return i; } } diff --git a/libnymea/network/networkdevicediscovery.h b/libnymea/network/networkdevicediscovery.h index 1934b960..fa216def 100644 --- a/libnymea/network/networkdevicediscovery.h +++ b/libnymea/network/networkdevicediscovery.h @@ -44,6 +44,8 @@ #include "macaddressdatabasereply.h" #include "networkdevicediscoveryreply.h" +#include "integrations/thing.h" + class LIBNYMEA_EXPORT NetworkDeviceDiscovery : public HardwareResource { Q_OBJECT @@ -55,9 +57,7 @@ public: virtual bool running() const = 0; - virtual NetworkDeviceMonitor *registerMonitor(const MacAddress &macAddress) = 0; - - virtual void unregisterMonitor(const MacAddress &macAddress) = 0; + virtual NetworkDeviceMonitor *registerMonitor(Thing *thing) = 0; virtual void unregisterMonitor(NetworkDeviceMonitor *networkDeviceMonitor) = 0; virtual PingReply *ping(const QHostAddress &address, uint retries = 3) = 0; diff --git a/libnymea/network/networkdeviceinfo.cpp b/libnymea/network/networkdeviceinfo.cpp index e6e6e6e3..adcbfc71 100644 --- a/libnymea/network/networkdeviceinfo.cpp +++ b/libnymea/network/networkdeviceinfo.cpp @@ -146,7 +146,7 @@ QString NetworkDeviceInfo::incompleteProperties() const list.append("MAC infos incomplete"); if (!m_hostNameSet) - list.append("hostname not set"); + list.append("host name not set"); if (!m_networkInterfaceSet) list.append("nework interface not set"); @@ -154,6 +154,48 @@ QString NetworkDeviceInfo::incompleteProperties() const return list.join(", "); } +QString NetworkDeviceInfo::thingParamValueMacAddress() const +{ + QString macString; + switch (m_monitorMode) { + case MonitorModeMac: + macString = m_macAddressInfos.constFirst().macAddress().toString(); + break; + default: + // In any other case we don't want to store the mac address since we can not relai on it + break; + } + return macString; +} + +QString NetworkDeviceInfo::thingParamValueHostName() const +{ + QString hostNameString; + switch (m_monitorMode) { + case MonitorModeMac: + case MonitorModeHostName: + hostNameString = m_hostName; + break; + default: + break; + } + return hostNameString; +} + +QString NetworkDeviceInfo::thingParamValueAddress() const +{ + QString addressString; + switch (m_monitorMode) { + case MonitorModeIp: + addressString = m_address.toString(); + break; + default: + // In any other case we don't want to store the IP address because we want to discover it + break; + } + return addressString; +} + bool NetworkDeviceInfo::operator==(const NetworkDeviceInfo &other) const { return m_address == other.address() && @@ -179,7 +221,7 @@ QDebug operator<<(QDebug dbg, const NetworkDeviceInfo &networkDeviceInfo) case NetworkDeviceInfo::MonitorModeMac: dbg.nospace().noquote() << "MAC"; break; - case NetworkDeviceInfo::MonitorModeHostname: + case NetworkDeviceInfo::MonitorModeHostName: dbg.nospace().noquote() << "hostname"; break; case NetworkDeviceInfo::MonitorModeIp: diff --git a/libnymea/network/networkdeviceinfo.h b/libnymea/network/networkdeviceinfo.h index 2d9e62df..9e6c8e13 100644 --- a/libnymea/network/networkdeviceinfo.h +++ b/libnymea/network/networkdeviceinfo.h @@ -44,17 +44,10 @@ class LIBNYMEA_EXPORT NetworkDeviceInfo { Q_GADGET public: - // Virtual hosts are devices with no MAC address available or not unique MAC address and the MAC address can not be used for the NetworkDeviceMonitor. - // Examples for virtual hosts are - // - VPN network hosts (no MAC address) - // - Webservers outside the network (domains) - // - Devices behind older wifi repeaters, multiple hosts (individual devices) have the same virtual MAC address - // - Hosts which are accessable over multiple interfaces within the same network (i.e. WLAN + LAN), - // they can be reached using both MAC addresses and both IP addresses (linux feature) enum MonitorMode { MonitorModeMac = 0x01, // Unique MAC address within the network - MonitorModeHostname = 0x02, // DNS hostname available, but no MAC address or not unique MAC available + MonitorModeHostName = 0x02, // DNS hostname available, but no MAC address or not unique MAC available MonitorModeIp = 0x03 // Only the IP can be used to monitor, simple ping on reachable }; Q_ENUM(MonitorMode) @@ -86,6 +79,13 @@ public: QString incompleteProperties() const; + // Helper methods for the networkdevice interface + // The fill in automaticlally the correct paramters for the + // right monitor + QString thingParamValueMacAddress() const; + QString thingParamValueHostName() const; + QString thingParamValueAddress() const; + bool operator==(const NetworkDeviceInfo &other) const; bool operator!=(const NetworkDeviceInfo &other) const; diff --git a/libnymea/network/networkdeviceinfos.cpp b/libnymea/network/networkdeviceinfos.cpp index 0f0c750a..91e54ee9 100644 --- a/libnymea/network/networkdeviceinfos.cpp +++ b/libnymea/network/networkdeviceinfos.cpp @@ -108,36 +108,6 @@ void NetworkDeviceInfos::removeHostAddress(const QHostAddress &address) } } -// NetworkDeviceInfo NetworkDeviceInfos::get(const QString &macAddress) const -// { -// foreach (const NetworkDeviceInfo &networkDeviceInfo, *this) { -// if (networkDeviceInfo.macAddress() == macAddress) { -// return networkDeviceInfo; -// } -// } - -// return NetworkDeviceInfo(); -// } - -// NetworkDeviceInfo NetworkDeviceInfos::get(const MacAddress &macAddress) const -// { -// return get(macAddress.toString()); -// } - -// void NetworkDeviceInfos::removeMacAddress(const QString &macAddress) -// { -// removeMacAddress(MacAddress(macAddress)); -// } - -// void NetworkDeviceInfos::removeMacAddress(const MacAddress &macAddress) -// { -// for (int i = 0; i < size(); i++) { -// if (MacAddress(at(i).macAddress()) == macAddress) { -// remove(i); -// } -// } -// } - void NetworkDeviceInfos::sortNetworkDevices() { std::sort(this->begin(), this->end(), [](const NetworkDeviceInfo& a, const NetworkDeviceInfo& b) { diff --git a/libnymea/network/networkdeviceinfos.h b/libnymea/network/networkdeviceinfos.h index 22fd8c4e..d1302873 100644 --- a/libnymea/network/networkdeviceinfos.h +++ b/libnymea/network/networkdeviceinfos.h @@ -52,11 +52,6 @@ public: bool hasMacAddress(const MacAddress &macAddress); NetworkDeviceInfo get(const QHostAddress &address) const; - // NetworkDeviceInfo get(const QString &macAddress) const; - // NetworkDeviceInfo get(const MacAddress &macAddress) const; - - // void removeMacAddress(const QString &macAddress); - // void removeMacAddress(const MacAddress &macAddress); void removeHostAddress(const QHostAddress &address); void sortNetworkDevices(); diff --git a/libnymea/network/networkdevicemonitor.cpp b/libnymea/network/networkdevicemonitor.cpp index 453e4612..ab8b9f50 100644 --- a/libnymea/network/networkdevicemonitor.cpp +++ b/libnymea/network/networkdevicemonitor.cpp @@ -40,13 +40,20 @@ NetworkDeviceMonitor::NetworkDeviceMonitor(QObject *parent) : QDebug operator<<(QDebug dbg, NetworkDeviceMonitor *networkDeviceMonitor) { QDebugStateSaver saver(dbg); - dbg.nospace() << "NetworkDeviceMonitor(" << networkDeviceMonitor->macAddress().toString(); + dbg.nospace() << "NetworkDeviceMonitor("; - // FIXME - // if (!networkDeviceMonitor->networkDeviceInfo().macAddressManufacturer().isEmpty()) - // dbg.nospace() << " - " << networkDeviceMonitor->networkDeviceInfo().macAddressManufacturer(); + switch (networkDeviceMonitor->monitorMode()) { + case NetworkDeviceInfo::MonitorModeMac: + dbg.nospace() << "Mode: MAC, " << networkDeviceMonitor->macAddress().toString(); + break; + case NetworkDeviceInfo::MonitorModeHostName: + dbg.nospace() << "Mode: host name, " << networkDeviceMonitor->hostName(); + break; + case NetworkDeviceInfo::MonitorModeIp: + dbg.nospace() << "Mode: IP address, " << networkDeviceMonitor->address().toString(); + break; + } - dbg.nospace() << ", " << networkDeviceMonitor->networkDeviceInfo().address().toString(); dbg.nospace() << ", " << (networkDeviceMonitor->reachable() ? "reachable" : "not reachable"); dbg.nospace() << ")"; return dbg; diff --git a/libnymea/network/networkdevicemonitor.h b/libnymea/network/networkdevicemonitor.h index dcd8f459..172c36c2 100644 --- a/libnymea/network/networkdevicemonitor.h +++ b/libnymea/network/networkdevicemonitor.h @@ -35,7 +35,6 @@ #include #include "libnymea.h" -#include "macaddress.h" #include "networkdeviceinfo.h" class LIBNYMEA_EXPORT NetworkDeviceMonitor : public QObject @@ -46,8 +45,14 @@ public: explicit NetworkDeviceMonitor(QObject *parent = nullptr); virtual ~NetworkDeviceMonitor() = default; + // Monitor parameters defining the monitor mode virtual MacAddress macAddress() const = 0; + virtual QString hostName() const = 0; + virtual QHostAddress address() const = 0; + virtual NetworkDeviceInfo::MonitorMode monitorMode() const = 0; + + // Actual network device information virtual NetworkDeviceInfo networkDeviceInfo() const = 0; virtual bool reachable() const = 0; @@ -60,7 +65,7 @@ signals: void reachableChanged(bool reachable); void lastSeenChanged(const QDateTime &lastSeen); void networkDeviceInfoChanged(const NetworkDeviceInfo &networkDeviceInfo); - + void pingRetriesChanged(uint pingRetries); }; QDebug operator<<(QDebug debug, NetworkDeviceMonitor *networkDeviceMonitor);