added async device setup

This commit is contained in:
Boernsman 2020-02-10 21:57:53 +05:00 committed by bernhard.trinnes
parent c57cfc59f0
commit 11c978191f
4 changed files with 128 additions and 53 deletions

View File

@ -83,38 +83,57 @@ void DevicePluginDoorbird::discoverDevices(DeviceDiscoveryInfo *info)
info->finish(Device::DeviceErrorNoError); info->finish(Device::DeviceErrorNoError);
}); });
return; return;
} else {
qCWarning(dcDoorBird()) << "Cannot discover for deviceClassId" << info->deviceClassId();
info->finish(Device::DeviceErrorDeviceNotFound);
} }
qCWarning(dcDoorBird()) << "Cannot discover for deviceClassId" << info->deviceClassId();
info->finish(Device::DeviceErrorDeviceNotFound);
} }
void DevicePluginDoorbird::startPairing(DevicePairingInfo *info) void DevicePluginDoorbird::startPairing(DevicePairingInfo *info)
{ {
if (info->deviceClassId() == doorBirdDeviceClassId) { if (info->deviceClassId() == doorBirdDeviceClassId) {
qCDebug(dcDoorBird()) << "User and password. Login is \"user\" and \"password\"."; info->finish(Device::DeviceErrorNoError, QT_TR_NOOP("Please enter username and password for the DoorBird device"));
info->finish(Device::DeviceErrorNoError, QT_TR_NOOP("Please enter the user credentials"));
return; return;
} else {
qCWarning(dcDoorBird()) << "StartPairing unhandled deviceClassId" << info->deviceClassId();
info->finish(Device::DeviceErrorCreationMethodNotSupported);
} }
info->finish(Device::DeviceErrorCreationMethodNotSupported);
} }
void DevicePluginDoorbird::confirmPairing(DevicePairingInfo *info, const QString &username, const QString &secret) void DevicePluginDoorbird::confirmPairing(DevicePairingInfo *info, const QString &username, const QString &password)
{ {
if (info->deviceClassId() == doorBirdDeviceClassId) { if (info->deviceClassId() == doorBirdDeviceClassId) {
qCDebug(dcDoorBird()) << "confirm pairing called"; QHostAddress address = QHostAddress(info->params().paramValue(doorBirdDeviceAddressParamTypeId).toString());
Doorbird *doorbird = new Doorbird(address, this);
connect(doorbird, &Doorbird::deviceConnected, this, &DevicePluginDoorbird::onDoorBirdConnected);
connect(doorbird, &Doorbird::eventReveiced, this, &DevicePluginDoorbird::onDoorBirdEvent);
connect(doorbird, &Doorbird::requestSent, this, &DevicePluginDoorbird::onDoorBirdRequestSent);
connect(doorbird, &Doorbird::sessionIdReceived, this, &DevicePluginDoorbird::onSessionIdReceived);
doorbird->initConnection(username, password);
doorbird->connectToEventMonitor();
m_doorbirdConnections.insert(info->deviceId(), doorbird);
m_pendingPairings.insert(doorbird, info);
doorbird->getSession();
connect(info, &DevicePairingInfo::aborted, this, [this, info]{
if (m_pendingPairings.values().contains(info)) {
Doorbird *doorbird = m_pendingPairings.key(info);
m_pendingPairings.remove(doorbird);
doorbird->deleteLater();
}
m_doorbirdConnections.remove(info->deviceId());
});
pluginStorage()->beginGroup(info->deviceId().toString()); pluginStorage()->beginGroup(info->deviceId().toString());
pluginStorage()->setValue("username", username); pluginStorage()->setValue("username", username);
pluginStorage()->setValue("password", secret); pluginStorage()->setValue("password", password);
pluginStorage()->endGroup(); pluginStorage()->endGroup();
} else {
info->finish(Device::DeviceErrorNoError); qCWarning(dcDoorBird()) << "Confirm pairing DeviceClassNotFound" << info->deviceClassId();
return; info->finish(Device::DeviceErrorDeviceClassNotFound);
} }
info->finish(Device::DeviceErrorDeviceClassNotFound);
return;
} }
@ -125,30 +144,45 @@ void DevicePluginDoorbird::setupDevice(DeviceSetupInfo *info)
if (device->deviceClassId() == doorBirdDeviceClassId) { if (device->deviceClassId() == doorBirdDeviceClassId) {
QHostAddress address = QHostAddress(device->paramValue(doorBirdDeviceAddressParamTypeId).toString()); QHostAddress address = QHostAddress(device->paramValue(doorBirdDeviceAddressParamTypeId).toString());
pluginStorage()->beginGroup(device->id().toString()); if (m_doorbirdConnections.contains(device->id())) {
QString username = pluginStorage()->value("username").toString(); info->finish(Device::DeviceErrorNoError);
QString password = pluginStorage()->value("password").toString(); } else {
pluginStorage()->endGroup(); pluginStorage()->beginGroup(device->id().toString());
QString username = pluginStorage()->value("username").toString();
QString password = pluginStorage()->value("password").toString();
pluginStorage()->endGroup();
qCDebug(dcDoorBird()) << "Device setup" << device->name() << username << password; qCDebug(dcDoorBird()) << "Device setup" << device->name() << username << password;
Doorbird *doorbird = new Doorbird(address, username, password, this); Doorbird *doorbird = new Doorbird(address, this);
connect(doorbird, &Doorbird::deviceConnected, this, &DevicePluginDoorbird::onDoorBirdConnected); connect(doorbird, &Doorbird::deviceConnected, this, &DevicePluginDoorbird::onDoorBirdConnected);
connect(doorbird, &Doorbird::eventReveiced, this, &DevicePluginDoorbird::onDoorBirdEvent); connect(doorbird, &Doorbird::eventReveiced, this, &DevicePluginDoorbird::onDoorBirdEvent);
connect(doorbird, &Doorbird::requestSent, this, &DevicePluginDoorbird::onDoorBirdRequestSent); connect(doorbird, &Doorbird::requestSent, this, &DevicePluginDoorbird::onDoorBirdRequestSent);
doorbird->connectToEventMonitor(); connect(doorbird, &Doorbird::sessionIdReceived, this, &DevicePluginDoorbird::onSessionIdReceived);
m_doorbirdConnections.insert(device, doorbird); doorbird->initConnection(username, password);
info->finish(Device::DeviceErrorNoError); doorbird->connectToEventMonitor();
return; m_doorbirdConnections.insert(device->id(), doorbird);
m_pendingDeviceSetups.insert(doorbird, info);
doorbird->getSession();
connect(info, &DeviceSetupInfo::aborted, this, [device, doorbird, this] {
if (!doorbird) {
doorbird->deleteLater();
}
m_doorbirdConnections.remove(device->id());
m_pendingPairings.remove(doorbird);
});
}
} else {
qCWarning(dcDoorBird()) << "Unhandled device class" << info->device()->deviceClass();
info->finish(Device::DeviceErrorDeviceClassNotFound);
} }
qCWarning(dcDoorBird()) << "Unhandled device class" << info->device()->deviceClass();
info->finish(Device::DeviceErrorDeviceClassNotFound);
} }
void DevicePluginDoorbird::postSetupDevice(Device *device) void DevicePluginDoorbird::postSetupDevice(Device *device)
{ {
if (device->deviceClassId() == doorBirdDeviceClassId) { if (device->deviceClassId() == doorBirdDeviceClassId) {
Doorbird *doorbird = m_doorbirdConnections.value(device); device->setStateValue(doorBirdConnectedStateTypeId, true); //since we checked the connection in the deviceSetup
Doorbird *doorbird = m_doorbirdConnections.value(device->id());
doorbird->infoRequest(); doorbird->infoRequest();
doorbird->listFavorites(); doorbird->listFavorites();
doorbird->listSchedules(); doorbird->listSchedules();
@ -162,7 +196,7 @@ void DevicePluginDoorbird::executeAction(DeviceActionInfo *info)
Action action = info->action(); Action action = info->action();
if (device->deviceClassId() == doorBirdDeviceClassId) { if (device->deviceClassId() == doorBirdDeviceClassId) {
Doorbird *doorbird = m_doorbirdConnections.value(device); Doorbird *doorbird = m_doorbirdConnections.value(device->id());
if (!doorbird) { if (!doorbird) {
info->finish(Device::DeviceErrorHardwareFailure); info->finish(Device::DeviceErrorHardwareFailure);
return; return;
@ -180,17 +214,20 @@ void DevicePluginDoorbird::executeAction(DeviceActionInfo *info)
doorbird->restart(); doorbird->restart();
info->finish(Device::DeviceErrorNoError); info->finish(Device::DeviceErrorNoError);
return; return;
} else {
qCWarning(dcDoorBird()) << "Unhandled ActionTypeId:" << action.actionTypeId();
info->finish(Device::DeviceErrorActionTypeNotFound);
} }
info->finish(Device::DeviceErrorActionTypeNotFound); } else {
return; qCWarning(dcDoorBird()) << "Execute action, unhandled device class" << device->deviceClass();
info->finish(Device::DeviceErrorDeviceClassNotFound);
} }
info->finish(Device::DeviceErrorDeviceClassNotFound);
} }
void DevicePluginDoorbird::deviceRemoved(Device *device) void DevicePluginDoorbird::deviceRemoved(Device *device)
{ {
if (device->deviceClassId() == doorBirdDeviceClassId) { if (device->deviceClassId() == doorBirdDeviceClassId) {
Doorbird *doorbirdConnection = m_doorbirdConnections.take(device); Doorbird *doorbirdConnection = m_doorbirdConnections.take(device->id());
doorbirdConnection->deleteLater(); doorbirdConnection->deleteLater();
} }
} }
@ -198,7 +235,7 @@ void DevicePluginDoorbird::deviceRemoved(Device *device)
void DevicePluginDoorbird::onDoorBirdConnected(bool status) void DevicePluginDoorbird::onDoorBirdConnected(bool status)
{ {
Doorbird *doorbird = static_cast<Doorbird *>(sender()); Doorbird *doorbird = static_cast<Doorbird *>(sender());
Device *device = m_doorbirdConnections.key(doorbird); Device *device = myDevices().findById(m_doorbirdConnections.key(doorbird));
if (!device) if (!device)
return; return;
@ -208,7 +245,7 @@ void DevicePluginDoorbird::onDoorBirdConnected(bool status)
void DevicePluginDoorbird::onDoorBirdEvent(Doorbird::EventType eventType, bool status) void DevicePluginDoorbird::onDoorBirdEvent(Doorbird::EventType eventType, bool status)
{ {
Doorbird *doorbird = static_cast<Doorbird *>(sender()); Doorbird *doorbird = static_cast<Doorbird *>(sender());
Device *device = m_doorbirdConnections.key(doorbird); Device *device = myDevices().findById(m_doorbirdConnections.key(doorbird));
if (!device) if (!device)
return; return;
@ -232,7 +269,7 @@ void DevicePluginDoorbird::onDoorBirdEvent(Doorbird::EventType eventType, bool s
void DevicePluginDoorbird::onDoorBirdRequestSent(QUuid requestId, bool success) void DevicePluginDoorbird::onDoorBirdRequestSent(QUuid requestId, bool success)
{ {
Doorbird *doorbird = static_cast<Doorbird *>(sender()); Doorbird *doorbird = static_cast<Doorbird *>(sender());
Device *device = m_doorbirdConnections.key(doorbird); Device *device = myDevices().findById(m_doorbirdConnections.key(doorbird));
if (!device) if (!device)
return; return;
@ -242,3 +279,19 @@ void DevicePluginDoorbird::onDoorBirdRequestSent(QUuid requestId, bool success)
DeviceActionInfo* actionInfo = m_asyncActions.take(requestId); DeviceActionInfo* actionInfo = m_asyncActions.take(requestId);
actionInfo->finish(success ? Device::DeviceErrorNoError : Device::DeviceErrorInvalidParameter); actionInfo->finish(success ? Device::DeviceErrorNoError : Device::DeviceErrorInvalidParameter);
} }
void DevicePluginDoorbird::onSessionIdReceived(const QString &sessionId)
{
Q_UNUSED(sessionId);
Doorbird *doorbird = static_cast<Doorbird *>(sender());
if (m_pendingPairings.contains(doorbird)) {
DevicePairingInfo *info = m_pendingPairings.take(doorbird);
info->finish(Device::DeviceErrorNoError);
}
if (m_pendingDeviceSetups.contains(doorbird)) {
DeviceSetupInfo *info = m_pendingDeviceSetups.take(doorbird);
info->finish(Device::DeviceErrorNoError);
}
}

View File

@ -61,13 +61,17 @@ public:
void deviceRemoved(Device *device)override; void deviceRemoved(Device *device)override;
private: private:
QHash<Device*, Doorbird *> m_doorbirdConnections; QHash<DeviceId, Doorbird *> m_doorbirdConnections;
QHash<Doorbird *, DevicePairingInfo *> m_pendingPairings;
QHash<Doorbird *, DeviceSetupInfo *> m_pendingDeviceSetups;
QHash<QUuid, DeviceActionInfo *> m_asyncActions; QHash<QUuid, DeviceActionInfo *> m_asyncActions;
private slots: private slots:
void onDoorBirdConnected(bool status); void onDoorBirdConnected(bool status);
void onDoorBirdEvent(Doorbird::EventType eventType, bool status); void onDoorBirdEvent(Doorbird::EventType eventType, bool status);
void onDoorBirdRequestSent(QUuid requestId, bool success); void onDoorBirdRequestSent(QUuid requestId, bool success);
void onSessionIdReceived(const QString &sessionId);
}; };
#endif // DEVICEPLUGINDOORBIRD_H #endif // DEVICEPLUGINDOORBIRD_H

View File

@ -41,18 +41,30 @@
#include <QUrl> #include <QUrl>
#include <QUrlQuery> #include <QUrlQuery>
Doorbird::Doorbird(const QHostAddress &address, const QString &username, const QString &password, QObject *parent) : Doorbird::Doorbird(const QHostAddress &address, QObject *parent) :
QObject(parent), QObject(parent),
m_address(address), m_address(address)
m_username(username), {
m_password(password)
}
QHostAddress Doorbird::address()
{
return m_address;
}
void Doorbird::setAddress(const QHostAddress &address)
{
m_address = address;
}
void Doorbird::initConnection(const QString &username, const QString &password)
{ {
m_networkAccessManager = new QNetworkAccessManager(this); m_networkAccessManager = new QNetworkAccessManager(this);
connect(m_networkAccessManager, &QNetworkAccessManager::authenticationRequired, this, [this](QNetworkReply *reply, QAuthenticator *authenticator) { connect(m_networkAccessManager, &QNetworkAccessManager::authenticationRequired, this, [username, password, this](QNetworkReply *reply, QAuthenticator *authenticator) {
Q_UNUSED(reply); Q_UNUSED(reply);
qCDebug(dcDoorBird) << "Credentials requested:"; authenticator->setUser(username);
authenticator->setUser(m_username); authenticator->setPassword(password);
authenticator->setPassword(m_password);
}); });
} }
@ -67,12 +79,11 @@ QUuid Doorbird::getSession()
reply->deleteLater(); reply->deleteLater();
if (reply->error() != QNetworkReply::NoError) { if (reply->error() != QNetworkReply::NoError) {
qCWarning(dcDoorBird) << "Error unlatching DoorBird device"; qCWarning(dcDoorBird) << "Error DoorBird device";
emit requestSent(requestId, false); emit requestSent(requestId, false);
return; return;
} }
emit requestSent(requestId, true); emit requestSent(requestId, true);
QByteArray data = reply->readAll(); QByteArray data = reply->readAll();
QJsonParseError error; QJsonParseError error;
QJsonDocument jsonDoc = QJsonDocument::fromJson(data, &error); QJsonDocument jsonDoc = QJsonDocument::fromJson(data, &error);
@ -80,6 +91,12 @@ QUuid Doorbird::getSession()
qCWarning(dcDoorBird()) << "Error parsing json:" << data; qCWarning(dcDoorBird()) << "Error parsing json:" << data;
return; return;
} }
QVariantMap map = jsonDoc.toVariant().toMap().value("BHA").toMap();
if (map.contains("SESSIONID")) {
QString sessionId = map.value("SESSIONID").toString();
qCDebug(dcDoorBird) << "Got sessionId" << sessionId;
emit sessionIdReceived(sessionId);
}
}); });
return requestId; return requestId;
} }

View File

@ -41,7 +41,7 @@ class Doorbird : public QObject
{ {
Q_OBJECT Q_OBJECT
public: public:
explicit Doorbird(const QHostAddress &address, const QString &username, const QString &password, QObject *parent = nullptr); explicit Doorbird(const QHostAddress &address, QObject *parent = nullptr);
enum EventType { enum EventType {
Doorbell, Doorbell,
@ -61,6 +61,9 @@ public:
int id; int id;
}; };
QHostAddress address();
void setAddress(const QHostAddress &address);
void initConnection(const QString &username, const QString &password);
QUuid getSession(); QUuid getSession();
QUuid openDoor(int value); QUuid openDoor(int value);
QUuid lightOn(); QUuid lightOn();
@ -90,10 +93,7 @@ private:
QHostAddress m_address; QHostAddress m_address;
QList<QNetworkReply *> m_networkRequests; QList<QNetworkReply *> m_networkRequests;
QString m_username; //QByteArray sessionId;
QString m_password;
QByteArray sessionId;
signals: signals:
void deviceConnected(bool status); void deviceConnected(bool status);
@ -102,6 +102,7 @@ signals:
void eventReveiced(EventType eventType, bool status); void eventReveiced(EventType eventType, bool status);
void favoritesReceived(QList<FavoriteObject> favourites); void favoritesReceived(QList<FavoriteObject> favourites);
void sessionIdReceived(const QString &sessionId);
void liveImageReceived(QImage image); void liveImageReceived(QImage image);
public slots: public slots: