fix REST timeout reply

This commit is contained in:
Simon Stürz 2016-02-21 19:00:25 +01:00 committed by Michael Zanetti
parent 4ef747e846
commit d33f170106
8 changed files with 142 additions and 27 deletions

View File

@ -55,11 +55,41 @@
#include <QDebug>
#include <QStringList>
#include <QNetworkInterface>
DevicePluginWifiDetector::DevicePluginWifiDetector()
{
}
DeviceManager::DeviceSetupStatus DevicePluginWifiDetector::setupDevice(Device *device)
{
qCDebug(dcWifiDetector) << "Setup" << device->params();
return DeviceManager::DeviceSetupStatusSuccess;
}
DeviceManager::DeviceError DevicePluginWifiDetector::discoverDevices(const DeviceClassId &deviceClassId, const ParamList &params)
{
Q_UNUSED(params)
m_deviceDescriptors.clear();
if (deviceClassId != wifiDeviceClassId)
return DeviceManager::DeviceErrorDeviceClassNotFound;
foreach (const QHostAddress &address, QNetworkInterface::allAddresses()) {
// not localhost and IPv4
if (!address.isLoopback() && address.protocol() == QAbstractSocket::IPv4Protocol) {
QProcess *process = new QProcess(this);
qCDebug(dcWifiDetector) << "Discover interface" << address.toString();
connect(process, SIGNAL(finished(int, QProcess::ExitStatus)), this, SLOT(discoveryProcessFinished(int,QProcess::ExitStatus)));
process->start(QStringLiteral("nmap"), QStringList() << "-sP" << QString("%1/24").arg(address.toString()));
m_discoveryProcesses.append(process);
}
}
return DeviceManager::DeviceErrorAsync;
}
DeviceManager::HardwareResources DevicePluginWifiDetector::requiredHardware() const
{
return DeviceManager::HardwareResourceTimer;
@ -67,46 +97,90 @@ DeviceManager::HardwareResources DevicePluginWifiDetector::requiredHardware() co
void DevicePluginWifiDetector::guhTimer()
{
QProcess *p = new QProcess(this);
connect(p, SIGNAL(finished(int,QProcess::ExitStatus)), this, SLOT(processFinished(int,QProcess::ExitStatus)));
p->start(QStringLiteral("sudo"), QStringList() << "nmap" << "-sP" << "10.10.10.0/24");
foreach (const QHostAddress &address, QNetworkInterface::allAddresses()) {
// not localhost and IPv4
if (!address.isLoopback() && address.protocol() == QAbstractSocket::IPv4Protocol) {
QProcess *process = new QProcess(this);
connect(process, SIGNAL(finished(int, QProcess::ExitStatus)), this, SLOT(processFinished(int, QProcess::ExitStatus)));
process->start(QStringLiteral("nmap"), QStringList() << "-sP" << QString("%1/24").arg(address.toString()));
}
}
}
void DevicePluginWifiDetector::processFinished(int exitCode, QProcess::ExitStatus exitStatus)
{
QProcess *p = static_cast<QProcess*>(sender());
QProcess *process = static_cast<QProcess*>(sender());
if (exitCode != 0 || exitStatus != QProcess::NormalExit) {
qCWarning(dcWifiDetector) << "error performing network scan:" << p->readAllStandardError();
qCWarning(dcWifiDetector) << "Network scan error:" << process->readAllStandardError();
process->deleteLater();
return;
}
QList<Device*> watchedDevices = deviceManager()->findConfiguredDevices(supportedDevices().first().id());
if (watchedDevices.isEmpty()) {
p->deleteLater();
// return if there is no longer any device
if (myDevices().isEmpty()) {
process->deleteLater();
return;
}
QStringList foundDevices;
while(p->canReadLine()) {
QString result = QString::fromLatin1(p->readLine());
while(process->canReadLine()) {
QString result = QString::fromLatin1(process->readLine());
if (result.startsWith("MAC Address:")) {
QStringList lineParts = result.split(' ');
if (lineParts.count() > 3) {
QString addr = lineParts.at(2);
foundDevices << addr.toLower();
//qCDebug(dcWifiDetector) << result.remove("/n");
foundDevices << lineParts.at(2).toLower();
}
}
}
foreach (Device *device, watchedDevices) {
bool wasInRange = device->stateValue(inRangeStateTypeId).toBool();
bool wasFound = foundDevices.contains(device->paramValue("mac").toString().toLower());
if (wasInRange != wasFound) {
// check states
foreach (Device *device, myDevices()) {
bool wasFound = foundDevices.contains(device->paramValue("mac address").toString().toLower());
if (device->stateValue(inRangeStateTypeId).toBool() != wasFound) {
device->setStateValue(inRangeStateTypeId, wasFound);
}
}
p->deleteLater();
process->deleteLater();
}
void DevicePluginWifiDetector::discoveryProcessFinished(int exitCode, QProcess::ExitStatus exitStatus)
{
QProcess *process = static_cast<QProcess*>(sender());
qCDebug(dcWifiDetector) << "Discovery finished";
if (m_discoveryProcesses.contains(process)) {
m_discoveryProcesses.removeAll(process);
} else {
return;
}
if (exitCode != 0 || exitStatus != QProcess::NormalExit) {
qCWarning(dcWifiDetector) << "Network scan error:" << process->readAllStandardError();
process->deleteLater();
return;
}
while(process->canReadLine()) {
QString result = QString::fromLatin1(process->readLine());
if (result.startsWith("MAC Address:")) {
QStringList lineParts = result.split(' ');
if (lineParts.count() > 4) {
qCDebug(dcWifiDetector) << "-----------------------------------";
QString macAddress = lineParts.at(2).toLower();
int index = result.indexOf(lineParts.at(2));
QString name = result.right(result.length() - index - macAddress.length() - 1);
qCDebug(dcWifiDetector) << "Address :" << macAddress;
qCDebug(dcWifiDetector) << "Interface:" << name.remove(QRegExp("\\(|\\)"));
m_deviceDescriptors.append(DeviceDescriptor(wifiDeviceClassId, macAddress, name.remove(QRegExp("\\(|\\)"))));
}
}
}
if (m_discoveryProcesses.isEmpty()) {
emit devicesDiscovered(wifiDeviceClassId, m_deviceDescriptors);
}
}

View File

@ -36,12 +36,19 @@ class DevicePluginWifiDetector : public DevicePlugin
public:
explicit DevicePluginWifiDetector();
DeviceManager::DeviceSetupStatus setupDevice(Device *device) override;
DeviceManager::DeviceError discoverDevices(const DeviceClassId &deviceClassId, const ParamList &params) override;
DeviceManager::HardwareResources requiredHardware() const override;
void guhTimer() override;
private:
QList<QProcess *> m_discoveryProcesses;
QList<DeviceDescriptor> m_deviceDescriptors;
private slots:
void processFinished(int exitCode, QProcess::ExitStatus exitStatus);
void discoveryProcessFinished(int exitCode, QProcess::ExitStatus exitStatus);
};
#endif // DEVICEPLUGINWIFIDETECTOR_H

View File

@ -11,11 +11,12 @@
{
"deviceClassId": "bd216356-f1ec-4324-9785-6982d2174e17",
"name": "WiFi Device",
"idName": "wifi",
"basicTags": [
"Service",
"Device",
"Sensor"
],
"createMethods": ["user"],
"createMethods": ["user", "discovery"],
"paramTypes": [
{
"name": "name",
@ -23,7 +24,7 @@
"inputType": "TextLine"
},
{
"name": "mac",
"name": "mac address",
"type": "QString",
"inputType": "MacAddress"
}

View File

@ -286,6 +286,11 @@ void DeviceClassesResource::devicesDiscovered(const DeviceClassId &deviceClassId
qCDebug(dcRest) << "Discovery finished. Found" << deviceDescriptors.count() << "devices.";
if (m_discoverRequests.value(deviceClassId).isNull()) {
qCWarning(dcRest) << "Async reply for discovery does not exist any more (timeout).";
return;
}
HttpReply *reply = m_discoverRequests.take(deviceClassId);
reply->setHeader(HttpReply::ContentTypeHeader, "application/json; charset=\"utf-8\";");
reply->setPayload(QJsonDocument::fromVariant(JsonTypes::packDeviceDescriptors(deviceDescriptors)).toJson());

View File

@ -44,7 +44,7 @@ public:
HttpReply *proccessRequest(const HttpRequest &request, const QStringList &urlTokens) override;
private:
mutable QHash<DeviceClassId, HttpReply *> m_discoverRequests;
mutable QHash<DeviceClassId, QPointer<HttpReply>> m_discoverRequests;
DeviceClass m_deviceClass;

View File

@ -499,6 +499,11 @@ void DevicesResource::actionExecuted(const ActionId &actionId, DeviceManager::De
QVariantMap response;
response.insert("error", JsonTypes::deviceErrorToString(status));
if (m_asyncActionExecutions.value(actionId).isNull()) {
qCWarning(dcRest) << "Async reply for execute action does not exist any more (timeout).";
return;
}
HttpReply *reply = m_asyncActionExecutions.take(actionId);
reply->setHeader(HttpReply::ContentTypeHeader, "application/json; charset=\"utf-8\";");
if (status == DeviceManager::DeviceErrorNoError) {
@ -524,6 +529,11 @@ void DevicesResource::deviceSetupFinished(Device *device, DeviceManager::DeviceE
QVariantMap response;
response.insert("error", JsonTypes::deviceErrorToString(status));
if (m_asyncDeviceAdditions.value(device->id()).isNull()) {
qCWarning(dcRest) << "Async reply for device setup does not exist any more (timeout).";
return;
}
HttpReply *reply = m_asyncDeviceAdditions.take(device->id());
reply->setHeader(HttpReply::ContentTypeHeader, "application/json; charset=\"utf-8\";");
if (status == DeviceManager::DeviceErrorNoError) {
@ -550,6 +560,11 @@ void DevicesResource::deviceEditFinished(Device *device, DeviceManager::DeviceEr
QVariantMap response;
response.insert("error", JsonTypes::deviceErrorToString(status));
if (m_asyncEditDevice.value(device).isNull()) {
qCWarning(dcRest) << "Async reply for device edit does not exist any more (timeout).";
return;
}
HttpReply *reply = m_asyncEditDevice.take(device);
reply->setHeader(HttpReply::ContentTypeHeader, "application/json; charset=\"utf-8\";");
if (status == DeviceManager::DeviceErrorNoError) {
@ -573,6 +588,11 @@ void DevicesResource::pairingFinished(const PairingTransactionId &pairingTransac
QVariantMap response;
response.insert("error", JsonTypes::deviceErrorToString(status));
if (m_asyncPairingRequests.value(pairingTransactionId).isNull()) {
qCWarning(dcRest) << "Async reply for device pairing does not exist any more.";
return;
}
HttpReply *reply = m_asyncPairingRequests.take(pairingTransactionId);
if (status != DeviceManager::DeviceErrorNoError) {
qCDebug(dcRest) << "Pairing device finished with error.";
@ -582,6 +602,7 @@ void DevicesResource::pairingFinished(const PairingTransactionId &pairingTransac
reply->finished();
return;
}
qCDebug(dcRest) << "Pairing device finished successfully";
// Add device to async device addtions

View File

@ -43,10 +43,10 @@ public:
HttpReply *proccessRequest(const HttpRequest &request, const QStringList &urlTokens) override;
private:
mutable QHash<ActionId, HttpReply *> m_asyncActionExecutions;
mutable QHash<DeviceId, HttpReply *> m_asyncDeviceAdditions;
mutable QHash<Device *, HttpReply *> m_asyncEditDevice;
mutable QHash<PairingTransactionId, HttpReply *> m_asyncPairingRequests;
mutable QHash<ActionId, QPointer<HttpReply> > m_asyncActionExecutions;
mutable QHash<DeviceId, QPointer<HttpReply> > m_asyncDeviceAdditions;
mutable QHash<Device *, QPointer<HttpReply> > m_asyncEditDevice;
mutable QHash<PairingTransactionId, QPointer<HttpReply> > m_asyncPairingRequests;
Device *m_device;

View File

@ -138,6 +138,13 @@ void RestServer::processHttpRequest(const QUuid &clientId, const HttpRequest &re
void RestServer::asyncReplyFinished()
{
HttpReply *reply = qobject_cast<HttpReply*>(sender());
if (!m_asyncReplies.values().contains(reply)) {
qCWarning(dcWebServer) << "Reply for async request does no longer exist";
reply->deleteLater();
return;
}
QUuid clientId = m_asyncReplies.key(reply);
m_asyncReplies.remove(clientId);