mirror of https://github.com/nymea/nymea.git
reenable strict argument checking, now that we can mark parameters as optional
parent
913d544386
commit
c027bb1481
|
|
@ -31,6 +31,8 @@
|
|||
|
||||
The JSONRPC API is self documenting and can be introspected by calling \c"JSONRPC.Introspect".
|
||||
|
||||
Parameters are optional if the type is the type is prefixed with "o:" for optional.
|
||||
|
||||
\section1 Communicating with the server
|
||||
The server listens on TCP port 1234 for incoming TCP connections. It will respond to incoming
|
||||
connections with a some information about the server. Telnet can be used to issue commands for
|
||||
|
|
|
|||
|
|
@ -121,10 +121,20 @@ QList<Vendor> DeviceManager::supportedVendors() const
|
|||
return m_supportedVendors.values();
|
||||
}
|
||||
|
||||
/*! Returns all the supported \l{DeviceClass}{DeviceClasses} by all \l{DevicePlugin}{DevicePlugins} loaded in the system. */
|
||||
/*! Returns all the supported \l{DeviceClass}{DeviceClasses} by all \l{DevicePlugin}{DevicePlugins} loaded in the system.
|
||||
Optionally filtered by vendorId. */
|
||||
QList<DeviceClass> DeviceManager::supportedDevices(const VendorId &vendorId) const
|
||||
{
|
||||
return m_supportedDevices.values();
|
||||
qDebug() << "returning devices" << vendorId;
|
||||
QList<DeviceClass> ret;
|
||||
if (vendorId.isNull()) {
|
||||
ret = m_supportedDevices.values();
|
||||
} else {
|
||||
foreach (const DeviceClassId &deviceClassId, m_vendorDeviceMap.value(vendorId)) {
|
||||
ret.append(m_supportedDevices.value(deviceClassId));
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*! Add a new configured device for the given \l{DeviceClass} and the given parameters.
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
#ifndef TYPEUTILS_H
|
||||
#define TYPEUTILS_H
|
||||
|
||||
#include <QMetaType>
|
||||
#include <QUuid>
|
||||
|
||||
#define DECLARE_TYPE_ID(type) class type##Id: public QUuid \
|
||||
|
|
@ -10,12 +11,13 @@ public: \
|
|||
type##Id(): QUuid() {} \
|
||||
static type##Id create##type##Id() { return type##Id(QUuid::createUuid().toString()); } \
|
||||
static type##Id fromUuid(const QUuid &uuid) { return type##Id(uuid.toString()); } \
|
||||
};
|
||||
}; \
|
||||
Q_DECLARE_METATYPE(type##Id);
|
||||
|
||||
DECLARE_TYPE_ID(Device)
|
||||
DECLARE_TYPE_ID(DeviceClass)
|
||||
|
||||
DECLARE_TYPE_ID(Vendor)
|
||||
DECLARE_TYPE_ID(DeviceClass)
|
||||
DECLARE_TYPE_ID(Device)
|
||||
|
||||
DECLARE_TYPE_ID(EventType)
|
||||
DECLARE_TYPE_ID(StateType)
|
||||
|
|
|
|||
|
|
@ -40,7 +40,8 @@ DeviceHandler::DeviceHandler(QObject *parent) :
|
|||
setReturns("GetSupportedVendors", returns);
|
||||
|
||||
params.clear(); returns.clear();
|
||||
setDescription("GetSupportedDevices", "Returns a list of supported Device classes.");
|
||||
setDescription("GetSupportedDevices", "Returns a list of supported Device classes, optionally filtered by vendorId.");
|
||||
params.insert("vendorId", "o:uuid");
|
||||
setParams("GetSupportedDevices", params);
|
||||
QVariantList deviceClasses;
|
||||
deviceClasses.append(JsonTypes::deviceClassRef());
|
||||
|
|
@ -73,7 +74,7 @@ DeviceHandler::DeviceHandler(QObject *parent) :
|
|||
setParams("AddConfiguredDevice", params);
|
||||
returns.insert("success", "bool");
|
||||
returns.insert("errorMessage", "string");
|
||||
returns.insert("deviceId", "uuid");
|
||||
returns.insert("deviceId", "o:uuid");
|
||||
setReturns("AddConfiguredDevice", returns);
|
||||
|
||||
params.clear(); returns.clear();
|
||||
|
|
@ -126,7 +127,7 @@ DeviceHandler::DeviceHandler(QObject *parent) :
|
|||
setParams("GetStateValue", params);
|
||||
returns.insert("success", "bool");
|
||||
returns.insert("errorMessage", "string");
|
||||
returns.insert("value", "variant");
|
||||
returns.insert("value", "o:variant");
|
||||
setReturns("GetStateValue", returns);
|
||||
|
||||
// Notifications
|
||||
|
|
@ -158,10 +159,15 @@ QVariantMap DeviceHandler::GetSupportedVendors(const QVariantMap ¶ms) const
|
|||
|
||||
QVariantMap DeviceHandler::GetSupportedDevices(const QVariantMap ¶ms) const
|
||||
{
|
||||
Q_UNUSED(params)
|
||||
QVariantMap returns;
|
||||
QVariantList supportedDeviceList;
|
||||
foreach (const DeviceClass &deviceClass, GuhCore::instance()->deviceManager()->supportedDevices()) {
|
||||
QList<DeviceClass> supportedDevices;
|
||||
if (params.contains("vendorId")) {
|
||||
supportedDevices = GuhCore::instance()->deviceManager()->supportedDevices(VendorId(params.value("vendorId").toString()));
|
||||
} else {
|
||||
supportedDevices = GuhCore::instance()->deviceManager()->supportedDevices();
|
||||
}
|
||||
foreach (const DeviceClass &deviceClass, supportedDevices) {
|
||||
supportedDeviceList.append(JsonTypes::packDeviceClass(deviceClass));
|
||||
}
|
||||
returns.insert("deviceClasses", supportedDeviceList);
|
||||
|
|
@ -202,6 +208,7 @@ QVariantMap DeviceHandler::AddConfiguredDevice(const QVariantMap ¶ms)
|
|||
switch(status) {
|
||||
case DeviceManager::DeviceErrorNoError:
|
||||
returns.insert("success", true);
|
||||
returns.insert("errorMessage", "");
|
||||
returns.insert("deviceId", newDeviceId);
|
||||
break;
|
||||
case DeviceManager::DeviceErrorDeviceClassNotFound:
|
||||
|
|
@ -310,6 +317,7 @@ QVariantMap DeviceHandler::GetStateValue(const QVariantMap ¶ms) const
|
|||
QVariant stateValue = device->stateValue(params.value("stateTypeId").toUuid());
|
||||
|
||||
returns.insert("success", true);
|
||||
returns.insert("errorMessage", "");
|
||||
returns.insert("value", stateValue);
|
||||
return returns;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -192,7 +192,7 @@ void JsonRPCServer::processData(const QUuid &clientId, const QByteArray &jsonDat
|
|||
|
||||
QVariantMap returns;
|
||||
QMetaObject::invokeMethod(handler, method.toLatin1().data(), Q_RETURN_ARG(QVariantMap, returns), Q_ARG(QVariantMap, params));
|
||||
// Q_ASSERT((targetNamespace == "JSONRPC" && method == "Introspect") || handler->validateReturns(method, returns));
|
||||
Q_ASSERT((targetNamespace == "JSONRPC" && method == "Introspect") || handler->validateReturns(method, returns).first);
|
||||
sendResponse(clientId, commandId, returns);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -263,7 +263,10 @@ QPair<bool, QString> JsonTypes::validateMap(const QVariantMap &templateMap, cons
|
|||
{
|
||||
s_lastError.clear();
|
||||
foreach (const QString &key, templateMap.keys()) {
|
||||
if (key != "params" && !map.contains(key)) {
|
||||
if (templateMap.value(key).toString().startsWith("o:")) {
|
||||
continue;
|
||||
}
|
||||
if (!map.contains(key)) {
|
||||
qDebug() << "missing key" << key << templateMap << map;
|
||||
QJsonDocument jsonDoc = QJsonDocument::fromVariant(map);
|
||||
return report(false, QString("Missing key \"%1\" in %2").arg(key).arg(QString(jsonDoc.toJson())));
|
||||
|
|
@ -279,20 +282,23 @@ QPair<bool, QString> JsonTypes::validateMap(const QVariantMap &templateMap, cons
|
|||
|
||||
QPair<bool, QString> JsonTypes::validateProperty(const QVariant &templateValue, const QVariant &value)
|
||||
{
|
||||
if (templateValue == "uuid") {
|
||||
QString strippedTemplateValue = templateValue.toString();
|
||||
strippedTemplateValue.remove(QRegExp("^o:"));
|
||||
|
||||
if (strippedTemplateValue == "uuid") {
|
||||
QString errorString = QString("Param %1 is not a uuid.").arg(value.toString());
|
||||
return report(value.canConvert(QVariant::Uuid), errorString);
|
||||
}
|
||||
if (templateValue == "string") {
|
||||
if (strippedTemplateValue == "string") {
|
||||
QString errorString = QString("Param %1 is not a string.").arg(value.toString());
|
||||
return report(value.canConvert(QVariant::String), errorString);
|
||||
}
|
||||
if (templateValue == "bool") {
|
||||
if (strippedTemplateValue == "bool") {
|
||||
QString errorString = QString("Param %1 is not a bool.").arg(value.toString());
|
||||
return report(value.canConvert(QVariant::Bool), errorString);
|
||||
}
|
||||
qWarning() << QString("Unhandled property type: %1 (expected: %2)").arg(value.toString()).arg(templateValue.toString());
|
||||
QString errorString = QString("Unhandled property type: %1 (expected: %2)").arg(value.toString()).arg(templateValue.toString());
|
||||
qWarning() << QString("Unhandled property type: %1 (expected: %2)").arg(value.toString()).arg(strippedTemplateValue);
|
||||
QString errorString = QString("Unhandled property type: %1 (expected: %2)").arg(value.toString()).arg(strippedTemplateValue);
|
||||
return report(false, errorString);
|
||||
}
|
||||
|
||||
|
|
@ -339,6 +345,11 @@ QPair<bool, QString> JsonTypes::validateVariant(const QVariant &templateVariant,
|
|||
qDebug() << "device not valid";
|
||||
return result;
|
||||
}
|
||||
} else if (refName == vendorRef()) {
|
||||
QPair<bool, QString> result = validateMap(vendorDescription(), variant.toMap());
|
||||
if (!result.first) {
|
||||
qDebug() << "value not allowed in" << vendorRef();
|
||||
}
|
||||
} else if (refName == deviceClassRef()) {
|
||||
QPair<bool, QString> result = validateMap(deviceClassDescription(), variant.toMap());
|
||||
if (!result.first) {
|
||||
|
|
|
|||
|
|
@ -46,6 +46,8 @@ private slots:
|
|||
void introspect();
|
||||
|
||||
void getSupportedVendors();
|
||||
|
||||
void getSupportedDevices_data();
|
||||
void getSupportedDevices();
|
||||
|
||||
void enableDisableNotifications_data();
|
||||
|
|
@ -217,15 +219,34 @@ void TestJSONRPC::getSupportedVendors()
|
|||
QCOMPARE(vendorId, guhVendorId);
|
||||
}
|
||||
|
||||
void TestJSONRPC::getSupportedDevices_data()
|
||||
{
|
||||
QTest::addColumn<VendorId>("vendorId");
|
||||
QTest::addColumn<int>("resultCount");
|
||||
|
||||
QTest::newRow("vendor guh") << guhVendorId << 1;
|
||||
QTest::newRow("no filter") << VendorId() << 1;
|
||||
QTest::newRow("invalid vendor") << VendorId("93e7d361-8025-4354-b17e-b68406c800bc") << 0;
|
||||
}
|
||||
|
||||
void TestJSONRPC::getSupportedDevices()
|
||||
{
|
||||
QVariant supportedDevices = injectAndWait("Devices.GetSupportedDevices");
|
||||
QFETCH(VendorId, vendorId);
|
||||
QFETCH(int, resultCount);
|
||||
|
||||
QVariantMap params;
|
||||
if (!vendorId.isNull()) {
|
||||
params.insert("vendorId", vendorId);
|
||||
}
|
||||
QVariant supportedDevices = injectAndWait("Devices.GetSupportedDevices", params);
|
||||
|
||||
// Make sure there is exactly 1 supported device class with the name Mock Wifi Device
|
||||
QCOMPARE(supportedDevices.toMap().value("params").toMap().value("deviceClasses").toList().count(), 1);
|
||||
QCOMPARE(supportedDevices.toMap().value("params").toMap().value("deviceClasses").toList().count(), resultCount);
|
||||
if (resultCount > 0) {
|
||||
QString deviceName = supportedDevices.toMap().value("params").toMap().value("deviceClasses").toList().first().toMap().value("name").toString();
|
||||
QCOMPARE(deviceName, QString("Mock Device"));
|
||||
}
|
||||
}
|
||||
|
||||
void TestJSONRPC::enableDisableNotifications_data()
|
||||
{
|
||||
|
|
|
|||
Loading…
Reference in New Issue