From 8eeeeb12f6600cea24da9d6b98dd40ab4d6bc11b Mon Sep 17 00:00:00 2001 From: Michael Zanetti Date: Sun, 8 May 2022 14:45:16 +0200 Subject: [PATCH] minor fixes --- owlet/integrationpluginowlet.cpp | 81 ++++++++++++++++++++------------ owlet/integrationpluginowlet.h | 6 +++ owlet/owletclient.cpp | 47 +++++++++++++++--- owlet/owletclient.h | 13 ++++- 4 files changed, 109 insertions(+), 38 deletions(-) diff --git a/owlet/integrationpluginowlet.cpp b/owlet/integrationpluginowlet.cpp index 62374b007..bd6da390a 100644 --- a/owlet/integrationpluginowlet.cpp +++ b/owlet/integrationpluginowlet.cpp @@ -44,6 +44,7 @@ #include #include #include +#include IntegrationPluginOwlet::IntegrationPluginOwlet() { @@ -852,7 +853,55 @@ void IntegrationPluginOwlet::setupThing(ThingSetupInfo *info) params.insert("ledCount", thing->paramValue(ws2812ThingLedCountParamTypeId).toUInt()); params.insert("ledMode", "WS2812Mode" + thing->paramValue(ws2812ThingLedModeParamTypeId).toString()); params.insert("ledClock", "WS2812Clock" + thing->paramValue(ws2812ThingLedClockParamTypeId).toString()); - client->sendCommand("GPIO.ConfigurePin", params); + int id = client->sendCommand("GPIO.ConfigurePin", params); + connect(client, &OwletClient::replyReceived, thing, [id, client, thing](int commandId, const QVariantMap &/*params*/){ + if (id != commandId) + return; + + qCDebug(dcOwlet()) << "Configuration sent..."; + QVariantMap params; + params.insert("id", thing->paramValue(ws2812ThingPinParamTypeId).toUInt()); + params.insert("power", thing->stateValue(ws2812PowerStateTypeId).toBool()); + params.insert("brightness", thing->stateValue(ws2812BrightnessStateTypeId).toInt()); + QColor color = thing->stateValue(ws2812ColorStateTypeId).value(); + params.insert("color", (color.rgb() & 0xFFFFFF)); + int effect = thing->stateValue(ws2812EffectStateTypeId).toInt(); + params.insert("effect", effect); + qCDebug(dcOwlet()) << "Initializing" << QJsonDocument::fromVariant(params).toJson(); + client->sendCommand("GPIO.ControlPin", params); + + connect(client, &OwletClient::notificationReceived, thing, [=](const QString &name, const QVariantMap ¶ms){ + qCDebug(dcOwlet()) << "***Notif" << name << params; + if (thing->thingClassId() == digitalInputThingClassId) { + if (params.value("id").toInt() == thing->paramValue(digitalInputThingPinParamTypeId)) { + thing->setStateValue(digitalInputPowerStateTypeId, params.value("power").toBool()); + } + } + if (thing->thingClassId() == digitalOutputThingClassId) { + if (params.value("id").toInt() == thing->paramValue(digitalOutputThingPinParamTypeId)) { + thing->setStateValue(digitalOutputPowerStateTypeId, params.value("power").toBool()); + } + } + if (thing->thingClassId() == ws2812ThingClassId) { + if (name == "GPIO.PinChanged") { + if (params.contains("power")) { + thing->setStateValue(ws2812PowerStateTypeId, params.value("power").toBool()); + } + if (params.contains("brightness")) { + thing->setStateValue(ws2812BrightnessStateTypeId, params.value("brightness").toInt()); + } + if (params.contains("color")) { + thing->setStateValue(ws2812ColorStateTypeId, params.value("color").value()); + } + if (params.contains("effect")) { + thing->setStateValue(ws2812EffectStateTypeId, params.value("effect").toInt()); + } + } + } + }); + + }); + } @@ -870,36 +919,6 @@ void IntegrationPluginOwlet::setupThing(ThingSetupInfo *info) thing->setStateValue("connected", false); }); - connect(client, &OwletClient::notificationReceived, this, [=](const QString &name, const QVariantMap ¶ms){ - qCDebug(dcOwlet()) << "***Notif" << name << params; - if (thing->thingClassId() == digitalInputThingClassId) { - if (params.value("id").toInt() == thing->paramValue(digitalInputThingPinParamTypeId)) { - thing->setStateValue(digitalInputPowerStateTypeId, params.value("power").toBool()); - } - } - if (thing->thingClassId() == digitalOutputThingClassId) { - if (params.value("id").toInt() == thing->paramValue(digitalOutputThingPinParamTypeId)) { - thing->setStateValue(digitalOutputPowerStateTypeId, params.value("power").toBool()); - } - } - if (thing->thingClassId() == ws2812ThingClassId) { - if (name == "GPIO.PinChanged") { - if (params.contains("power")) { - thing->setStateValue(ws2812PowerStateTypeId, params.value("power").toBool()); - } - if (params.contains("brightness")) { - thing->setStateValue(ws2812BrightnessStateTypeId, params.value("brightness").toInt()); - } - if (params.contains("color")) { - thing->setStateValue(ws2812ColorStateTypeId, params.value("color").value()); - } - if (params.contains("effect")) { - thing->setStateValue(ws2812EffectStateTypeId, params.value("effect").toInt()); - } - } - } - }); - client->transport()->connectTransport(); } diff --git a/owlet/integrationpluginowlet.h b/owlet/integrationpluginowlet.h index 5d4a34367..779fd4e29 100644 --- a/owlet/integrationpluginowlet.h +++ b/owlet/integrationpluginowlet.h @@ -55,6 +55,9 @@ class IntegrationPluginOwlet: public IntegrationPlugin void executeAction(ThingActionInfo *info) override; void thingRemoved(Thing *thing) override; +private: + void processActionQueue(Thing *thing); + private: ZeroConfServiceBrowser *m_zeroConfBrowser = nullptr; @@ -76,6 +79,9 @@ class IntegrationPluginOwlet: public IntegrationPlugin void setupArduinoChildThing(OwletSerialClient *client, quint8 pinId, OwletSerialClient::PinMode pinMode); void configurePin(OwletSerialClient *client, quint8 pinId, OwletSerialClient::PinMode pinMode); QString getPinName(Thing *parent, quint8 pinId); + + QHash> m_actionQueue; + QHash m_pendingActions; }; #endif // INTEGRATIONPLUGINOWLET_H diff --git a/owlet/owletclient.cpp b/owlet/owletclient.cpp index 266571d3a..e3a6d5790 100644 --- a/owlet/owletclient.cpp +++ b/owlet/owletclient.cpp @@ -11,6 +11,17 @@ OwletClient::OwletClient(OwletTransport *transport, QObject *parent) : { transport->setParent(this); + m_commandTimeoutTimer.setInterval(5000); + connect(&m_commandTimeoutTimer, &QTimer::timeout, this, [=](){ + if (m_pendingCommandId != -1) { + QVariantMap params; + params.insert("error", "TimeoutError"); + emit replyReceived(m_pendingCommandId, params); + m_pendingCommandId = -1; + sendNextRequest(); + } + }); + connect(m_transport, &OwletTransport::dataReceived, this, &OwletClient::dataReceived); connect(m_transport, &OwletTransport::error, this, &OwletClient::error); connect(m_transport, &OwletTransport::connectedChanged, this, [=](bool isConnected){ @@ -39,13 +50,18 @@ int OwletClient::sendCommand(const QString &method, const QVariantMap ¶ms) return -1; } - int id = ++m_commandId; + quint16 id = ++m_commandId; QVariantMap packet; packet.insert("id", id); packet.insert("method", method); packet.insert("params", params); - m_transport->sendData(QJsonDocument::fromVariant(packet).toJson(QJsonDocument::Compact)); + qCDebug(dcOwlet) << "Sending command" << qUtf8Printable(QJsonDocument::fromVariant(packet).toJson()); + Command cmd; + cmd.id = id; + cmd.payload = packet; + m_commandQueue.append(cmd); + sendNextRequest(); return id; } @@ -60,10 +76,9 @@ void OwletClient::dataReceived(const QByteArray &data) QJsonParseError error; QJsonDocument jsonDoc = QJsonDocument::fromJson(m_receiveBuffer.left(splitIndex), &error); if (error.error != QJsonParseError::NoError) { - // qWarning() << "Could not parse json data from nymea" << m_receiveBuffer.left(splitIndex) << error.errorString(); + qCWarning(dcOwlet) << "Could not parse json data from nymea" << m_receiveBuffer.left(splitIndex) << error.errorString(); return; } - // qDebug() << "received response" << qUtf8Printable(jsonDoc.toJson(QJsonDocument::Indented)); m_receiveBuffer = m_receiveBuffer.right(m_receiveBuffer.length() - splitIndex - 1); if (!m_receiveBuffer.isEmpty()) { staticMetaObject.invokeMethod(this, "dataReceived", Qt::QueuedConnection, Q_ARG(QByteArray, QByteArray())); @@ -72,11 +87,31 @@ void OwletClient::dataReceived(const QByteArray &data) QVariantMap packet = jsonDoc.toVariant().toMap(); if (packet.contains("notification")) { - qCDebug(dcOwlet()) << "Notification received:" << packet; + qCDebug(dcOwlet()) << "Notification received:" << qUtf8Printable(QJsonDocument::fromVariant(packet).toJson()); emit notificationReceived(packet.value("notification").toString(), packet.value("params").toMap()); } else if (packet.contains("id")) { - qCDebug(dcOwlet()) << "reply received:" << packet; + qCDebug(dcOwlet()) << "Reply received:" << qUtf8Printable(QJsonDocument::fromVariant(packet).toJson()); int id = packet.value("id").toInt(); + if (id == m_pendingCommandId) { + m_pendingCommandId = -1; + sendNextRequest(); + } emit replyReceived(id, packet.value("params").toMap()); + } else { + qCWarning(dcOwlet) << "Unhandled data from owlet" << qUtf8Printable(jsonDoc.toJson(QJsonDocument::Indented)); + } +} + +void OwletClient::sendNextRequest() +{ + if (m_commandQueue.isEmpty()) { + return; + } + if (m_pendingCommandId != -1) { + return; } + Command cmd = m_commandQueue.takeFirst(); + m_pendingCommandId = cmd.id; + m_transport->sendData(QJsonDocument::fromVariant(cmd.payload).toJson(QJsonDocument::Compact)); + m_commandTimeoutTimer.start(); } diff --git a/owlet/owletclient.h b/owlet/owletclient.h index 9e7012a23..3af506c56 100644 --- a/owlet/owletclient.h +++ b/owlet/owletclient.h @@ -4,6 +4,7 @@ #include #include #include +#include class OwletTransport; @@ -30,12 +31,22 @@ class OwletClient : public QObject private slots: void dataReceived(const QByteArray &data); + void sendNextRequest(); + private: + struct Command { + int id; + QVariantMap payload; + }; OwletTransport *m_transport = nullptr; - int m_commandId = 0; + quint16 m_commandId = 0; QByteArray m_receiveBuffer; + QList m_commandQueue; + qint32 m_pendingCommandId = -1; + QTimer m_commandTimeoutTimer; + }; #endif // OWLETCLIENT_H