mirror of https://github.com/nymea/nymea.git
Merge PR #336: Add caching information to client API
commit
82c347c3a3
|
|
@ -45,6 +45,7 @@
|
|||
#include "integrations/browseritemresult.h"
|
||||
|
||||
#include <QDebug>
|
||||
#include <QJsonDocument>
|
||||
|
||||
namespace nymeaserver {
|
||||
|
||||
|
|
@ -400,6 +401,37 @@ DeviceHandler::DeviceHandler(QObject *parent) :
|
|||
connect(NymeaCore::instance(), &NymeaCore::thingAdded, this, &DeviceHandler::deviceAddedNotification);
|
||||
connect(NymeaCore::instance(), &NymeaCore::thingChanged, this, &DeviceHandler::deviceChangedNotification);
|
||||
connect(NymeaCore::instance(), &NymeaCore::thingSettingChanged, this, &DeviceHandler::deviceSettingChangedNotification);
|
||||
|
||||
connect(NymeaCore::instance(), &NymeaCore::initialized, this, [=](){
|
||||
// Generating cache hashes.
|
||||
// NOTE: We need to sort the lists to get a stable result
|
||||
QHash<ThingClassId, ThingClass> thingClassesMap;
|
||||
foreach (const ThingClass &tc, NymeaCore::instance()->thingManager()->supportedThings()) {
|
||||
thingClassesMap.insert(tc.id(), tc);
|
||||
}
|
||||
QList<ThingClassId> thingClassIds = thingClassesMap.keys();
|
||||
std::sort(thingClassIds.begin(), thingClassIds.end());
|
||||
DeviceClasses thingClasses;
|
||||
foreach (const ThingClassId &id, thingClassIds) {
|
||||
thingClasses.append(thingClassesMap.value(id));
|
||||
}
|
||||
QByteArray hash = QCryptographicHash::hash(QJsonDocument::fromVariant(pack(thingClasses)).toJson(), QCryptographicHash::Md5).toHex();
|
||||
m_cacheHashes.insert("GetSupportedDevices", hash);
|
||||
|
||||
QHash<VendorId, Vendor> vendorsMap;
|
||||
foreach (const Vendor &v, NymeaCore::instance()->thingManager()->supportedVendors()) {
|
||||
vendorsMap.insert(v.id(), v);
|
||||
}
|
||||
QList<VendorId> vendorIds = vendorsMap.keys();
|
||||
std::sort(vendorIds.begin(), vendorIds.end());
|
||||
Vendors vendors;
|
||||
foreach (const VendorId &id, vendorIds) {
|
||||
vendors.append(vendorsMap.value(id));
|
||||
}
|
||||
hash = QCryptographicHash::hash(QJsonDocument::fromVariant(pack(vendors)).toJson(), QCryptographicHash::Md5).toHex();
|
||||
m_cacheHashes.insert("GetSupportedVendors", hash);
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
/*! Returns the name of the \l{DeviceHandler}. In this case \b Devices.*/
|
||||
|
|
@ -408,6 +440,11 @@ QString DeviceHandler::name() const
|
|||
return "Devices";
|
||||
}
|
||||
|
||||
QHash<QString, QString> DeviceHandler::cacheHashes() const
|
||||
{
|
||||
return m_cacheHashes;
|
||||
}
|
||||
|
||||
JsonReply* DeviceHandler::GetSupportedVendors(const QVariantMap ¶ms, const JsonContext &context) const
|
||||
{
|
||||
Q_UNUSED(params)
|
||||
|
|
|
|||
|
|
@ -139,6 +139,8 @@ public:
|
|||
explicit DeviceHandler(QObject *parent = nullptr);
|
||||
|
||||
QString name() const override;
|
||||
QHash<QString, QString> cacheHashes() const override;
|
||||
|
||||
QVariantMap translateNotification(const QString ¬ification, const QVariantMap ¶ms, const QLocale &locale) override;
|
||||
|
||||
Q_INVOKABLE JsonReply *GetSupportedVendors(const QVariantMap ¶ms, const JsonContext &context) const;
|
||||
|
|
@ -196,6 +198,8 @@ private slots:
|
|||
|
||||
private:
|
||||
QVariantMap statusToReply(Device::ThingError status) const;
|
||||
|
||||
QHash<QString, QString> m_cacheHashes;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -45,6 +45,7 @@
|
|||
#include "integrations/browseritemresult.h"
|
||||
|
||||
#include <QDebug>
|
||||
#include <QJsonDocument>
|
||||
|
||||
namespace nymeaserver {
|
||||
|
||||
|
|
@ -445,6 +446,36 @@ IntegrationsHandler::IntegrationsHandler(ThingManager *thingManager, QObject *pa
|
|||
connect(NymeaCore::instance(), &NymeaCore::thingAdded, this, &IntegrationsHandler::thingAddedNotification);
|
||||
connect(NymeaCore::instance(), &NymeaCore::thingChanged, this, &IntegrationsHandler::thingChangedNotification);
|
||||
connect(NymeaCore::instance(), &NymeaCore::thingSettingChanged, this, &IntegrationsHandler::thingSettingChangedNotification);
|
||||
|
||||
connect(NymeaCore::instance(), &NymeaCore::initialized, this, [=](){
|
||||
// Generating cache hashes.
|
||||
// NOTE: We need to sort the lists to get a stable result
|
||||
QHash<ThingClassId, ThingClass> thingClassesMap;
|
||||
foreach (const ThingClass &tc, m_thingManager->supportedThings()) {
|
||||
thingClassesMap.insert(tc.id(), tc);
|
||||
}
|
||||
QList<ThingClassId> thingClassIds = thingClassesMap.keys();
|
||||
std::sort(thingClassIds.begin(), thingClassIds.end());
|
||||
ThingClasses thingClasses;
|
||||
foreach (const ThingClassId &id, thingClassIds) {
|
||||
thingClasses.append(thingClassesMap.value(id));
|
||||
}
|
||||
QByteArray hash = QCryptographicHash::hash(QJsonDocument::fromVariant(pack(thingClasses)).toJson(), QCryptographicHash::Md5).toHex();
|
||||
m_cacheHashes.insert("GetThingClasses", hash);
|
||||
|
||||
QHash<VendorId, Vendor> vendorsMap;
|
||||
foreach (const Vendor &v, m_thingManager->supportedVendors()) {
|
||||
vendorsMap.insert(v.id(), v);
|
||||
}
|
||||
QList<VendorId> vendorIds = vendorsMap.keys();
|
||||
std::sort(vendorIds.begin(), vendorIds.end());
|
||||
Vendors vendors;
|
||||
foreach (const VendorId &id, vendorIds) {
|
||||
vendors.append(vendorsMap.value(id));
|
||||
}
|
||||
hash = QCryptographicHash::hash(QJsonDocument::fromVariant(pack(vendors)).toJson(), QCryptographicHash::Md5).toHex();
|
||||
m_cacheHashes.insert("GetVendors", hash);
|
||||
});
|
||||
}
|
||||
|
||||
QString IntegrationsHandler::name() const
|
||||
|
|
@ -452,6 +483,11 @@ QString IntegrationsHandler::name() const
|
|||
return "Integrations";
|
||||
}
|
||||
|
||||
QHash<QString, QString> IntegrationsHandler::cacheHashes() const
|
||||
{
|
||||
return m_cacheHashes;
|
||||
}
|
||||
|
||||
JsonReply* IntegrationsHandler::GetVendors(const QVariantMap ¶ms, const JsonContext &context) const
|
||||
{
|
||||
Q_UNUSED(params)
|
||||
|
|
|
|||
|
|
@ -43,6 +43,7 @@ public:
|
|||
explicit IntegrationsHandler(ThingManager *thingManager, QObject *parent = nullptr);
|
||||
|
||||
QString name() const override;
|
||||
QHash<QString, QString> cacheHashes() const override;
|
||||
|
||||
Q_INVOKABLE JsonReply *GetVendors(const QVariantMap ¶ms, const JsonContext &context) const;
|
||||
Q_INVOKABLE JsonReply *GetThingClasses(const QVariantMap ¶ms, const JsonContext &context) const;
|
||||
|
|
@ -105,6 +106,8 @@ private slots:
|
|||
private:
|
||||
ThingManager *m_thingManager = nullptr;
|
||||
QVariantMap statusToReply(Thing::ThingError status) const;
|
||||
|
||||
QHash<QString, QString> m_cacheHashes;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -101,6 +101,11 @@ JsonRPCServerImplementation::JsonRPCServerImplementation(const QSslConfiguration
|
|||
experiece.insert("version", enumValueName(String));
|
||||
registerObject("Experience", experiece);
|
||||
|
||||
QVariantMap cacheHash;
|
||||
cacheHash.insert("method", enumValueName(String));
|
||||
cacheHash.insert("hash", enumValueName(String));
|
||||
registerObject("CacheHash", cacheHash);
|
||||
|
||||
// Methods
|
||||
QString description; QVariantMap returns; QVariantMap params;
|
||||
description = "Initiates a connection. Use this method to perform an initial handshake of the "
|
||||
|
|
@ -111,7 +116,10 @@ JsonRPCServerImplementation::JsonRPCServerImplementation(const QSslConfiguration
|
|||
"about this core instance such as version information, uuid and its name. The locale value"
|
||||
"indicates the locale used for this connection. Note: This method can be called multiple "
|
||||
"times. The locale used in the last call for this connection will be used. Other values, "
|
||||
"like initialSetupRequired might change if the setup has been performed in the meantime.";
|
||||
"like initialSetupRequired might change if the setup has been performed in the meantime.\n "
|
||||
"The field cacheHashes may contain a map of methods and MD5 hashes. As long as the hash for "
|
||||
"a method does not change, a client may use a previously cached copy of the call instead of "
|
||||
"fetching the content again.";
|
||||
params.insert("o:locale", enumValueName(String));
|
||||
returns.insert("server", enumValueName(String));
|
||||
returns.insert("name", enumValueName(String));
|
||||
|
|
@ -124,6 +132,7 @@ JsonRPCServerImplementation::JsonRPCServerImplementation(const QSslConfiguration
|
|||
returns.insert("authenticationRequired", enumValueName(Bool));
|
||||
returns.insert("pushButtonAuthAvailable", enumValueName(Bool));
|
||||
returns.insert("o:experiences", QVariantList() << objectRef("Experience"));
|
||||
returns.insert("o:cacheHashes", QVariantList() << objectRef("CacheHash"));
|
||||
registerMethod("Hello", description, params, returns);
|
||||
|
||||
params.clear(); returns.clear();
|
||||
|
|
@ -555,6 +564,19 @@ QVariantMap JsonRPCServerImplementation::createWelcomeMessage(TransportInterface
|
|||
}
|
||||
handshake.insert("experiences", experiences);
|
||||
}
|
||||
QVariantList cacheHashes;
|
||||
foreach (const QString &handlerName, m_handlers.keys()) {
|
||||
QHash<QString, QString> hashes = m_handlers.value(handlerName)->cacheHashes();
|
||||
foreach (const QString &hashName, hashes.keys()) {
|
||||
QVariantMap cacheHash;
|
||||
cacheHash.insert("method", handlerName + "." + hashName);
|
||||
cacheHash.insert("hash", hashes.value(hashName));
|
||||
cacheHashes.append(cacheHash);
|
||||
}
|
||||
}
|
||||
if (!cacheHashes.isEmpty()) {
|
||||
handshake.insert("cacheHashes", cacheHashes);
|
||||
}
|
||||
return handshake;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -41,6 +41,11 @@ JsonHandler::JsonHandler(QObject *parent) : QObject(parent)
|
|||
registerEnum<BasicType>();
|
||||
}
|
||||
|
||||
QHash<QString, QString> JsonHandler::cacheHashes() const
|
||||
{
|
||||
return QHash<QString, QString>();
|
||||
}
|
||||
|
||||
QVariantMap JsonHandler::translateNotification(const QString ¬ification, const QVariantMap ¶ms, const QLocale &locale)
|
||||
{
|
||||
Q_UNUSED(notification)
|
||||
|
|
|
|||
|
|
@ -64,6 +64,7 @@ public:
|
|||
virtual ~JsonHandler() = default;
|
||||
|
||||
virtual QString name() const = 0;
|
||||
virtual QHash<QString, QString> cacheHashes() const;
|
||||
|
||||
virtual QVariantMap translateNotification(const QString ¬ification, const QVariantMap ¶ms, const QLocale &locale);
|
||||
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ NYMEA_VERSION_STRING=$$system('dpkg-parsechangelog | sed -n -e "s/^Version: //p"
|
|||
|
||||
# define protocol versions
|
||||
JSON_PROTOCOL_VERSION_MAJOR=5
|
||||
JSON_PROTOCOL_VERSION_MINOR=1
|
||||
JSON_PROTOCOL_VERSION_MINOR=2
|
||||
JSON_PROTOCOL_VERSION="$${JSON_PROTOCOL_VERSION_MAJOR}.$${JSON_PROTOCOL_VERSION_MINOR}"
|
||||
LIBNYMEA_API_VERSION_MAJOR=7
|
||||
LIBNYMEA_API_VERSION_MINOR=0
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
5.1
|
||||
5.2
|
||||
{
|
||||
"enums": {
|
||||
"BasicType": [
|
||||
|
|
@ -1240,7 +1240,7 @@
|
|||
}
|
||||
},
|
||||
"JSONRPC.Hello": {
|
||||
"description": "Initiates a connection. Use this method to perform an initial handshake of the connection. Optionally, a parameter \"locale\" is can be passed to set up the used locale for this connection. Strings such as ThingClass displayNames etc will be localized to this locale. If this parameter is omitted, the default system locale (depending on the configuration) is used. The reply of this method contains information about this core instance such as version information, uuid and its name. The locale valueindicates the locale used for this connection. Note: This method can be called multiple times. The locale used in the last call for this connection will be used. Other values, like initialSetupRequired might change if the setup has been performed in the meantime.",
|
||||
"description": "Initiates a connection. Use this method to perform an initial handshake of the connection. Optionally, a parameter \"locale\" is can be passed to set up the used locale for this connection. Strings such as ThingClass displayNames etc will be localized to this locale. If this parameter is omitted, the default system locale (depending on the configuration) is used. The reply of this method contains information about this core instance such as version information, uuid and its name. The locale valueindicates the locale used for this connection. Note: This method can be called multiple times. The locale used in the last call for this connection will be used. Other values, like initialSetupRequired might change if the setup has been performed in the meantime.\n The field cacheHashes may contain a map of methods and MD5 hashes. As long as the hash for a method does not change, a client may use a previously cached copy of the call instead of fetching the content again.",
|
||||
"params": {
|
||||
"o:locale": "String"
|
||||
},
|
||||
|
|
@ -1250,6 +1250,9 @@
|
|||
"language": "String",
|
||||
"locale": "String",
|
||||
"name": "String",
|
||||
"o:cacheHashes": [
|
||||
"$ref:CacheHash"
|
||||
],
|
||||
"o:experiences": [
|
||||
"$ref:Experience"
|
||||
],
|
||||
|
|
@ -2380,6 +2383,10 @@
|
|||
"o:mediaIcon": "$ref:MediaBrowserIcon",
|
||||
"thumbnail": "String"
|
||||
},
|
||||
"CacheHash": {
|
||||
"hash": "String",
|
||||
"method": "String"
|
||||
},
|
||||
"CalendarItem": {
|
||||
"duration": "Uint",
|
||||
"o:datetime": "Uint",
|
||||
|
|
|
|||
Loading…
Reference in New Issue