reworked jsonrpc server.
added introspection all calls and responses have now param validation
This commit is contained in:
parent
693519841f
commit
02c8e6e4b4
@ -1,19 +1,19 @@
|
||||
#include "action.h"
|
||||
|
||||
Action::Action(const QUuid &deviceId, const QUuid &id) :
|
||||
m_id(id),
|
||||
Action::Action(const QUuid &deviceId, const QUuid &actionTypeId) :
|
||||
m_actionTypeId(actionTypeId),
|
||||
m_deviceId(deviceId)
|
||||
{
|
||||
}
|
||||
|
||||
bool Action::isValid() const
|
||||
{
|
||||
return !m_id.isNull();
|
||||
return !m_actionTypeId.isNull() && !m_deviceId.isNull();
|
||||
}
|
||||
|
||||
QUuid Action::id() const
|
||||
QUuid Action::actionTypeId() const
|
||||
{
|
||||
return m_id;
|
||||
return m_actionTypeId;
|
||||
}
|
||||
|
||||
QUuid Action::deviceId() const
|
||||
@ -21,16 +21,6 @@ QUuid Action::deviceId() const
|
||||
return m_deviceId;
|
||||
}
|
||||
|
||||
QString Action::name() const
|
||||
{
|
||||
return m_name;
|
||||
}
|
||||
|
||||
void Action::setName(const QString &name)
|
||||
{
|
||||
m_name = name;
|
||||
}
|
||||
|
||||
QVariantMap Action::params() const
|
||||
{
|
||||
return m_params;
|
||||
|
||||
@ -7,23 +7,19 @@
|
||||
class Action
|
||||
{
|
||||
public:
|
||||
explicit Action(const QUuid &deviceId, const QUuid &id = QUuid::createUuid());
|
||||
explicit Action(const QUuid &deviceId, const QUuid &actionTypeId);
|
||||
|
||||
bool isValid() const;
|
||||
|
||||
QUuid id() const;
|
||||
QUuid actionTypeId() const;
|
||||
QUuid deviceId() const;
|
||||
|
||||
QString name() const;
|
||||
void setName(const QString &name);
|
||||
|
||||
QVariantMap params() const;
|
||||
void setParams(const QVariantMap ¶ms);
|
||||
|
||||
private:
|
||||
QUuid m_id;
|
||||
QUuid m_actionTypeId;
|
||||
QUuid m_deviceId;
|
||||
QString m_name;
|
||||
QVariantMap m_params;
|
||||
};
|
||||
|
||||
|
||||
@ -132,6 +132,20 @@ DeviceManager::DeviceError DeviceManager::executeAction(const Action &action)
|
||||
{
|
||||
foreach (Device *device, m_configuredDevices) {
|
||||
if (action.deviceId() == device->id()) {
|
||||
// found device
|
||||
|
||||
// Make sure this device has an action type with this id
|
||||
DeviceClass deviceClass = findDeviceClass(device->deviceClassId());
|
||||
bool found = false;
|
||||
foreach (const ActionType &actionType, deviceClass.actions()) {
|
||||
if (actionType.id() == action.actionTypeId()) {
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
return DeviceErrorActionTypeNotFound;
|
||||
}
|
||||
|
||||
m_devicePlugins.value(device->pluginId())->executeAction(device, action);
|
||||
return DeviceErrorNoError;
|
||||
}
|
||||
|
||||
@ -28,6 +28,7 @@ public:
|
||||
DeviceErrorNoError,
|
||||
DeviceErrorDeviceNotFound,
|
||||
DeviceErrorDeviceClassNotFound,
|
||||
DeviceErrorActionTypeNotFound,
|
||||
DeviceErrorMissingParameter,
|
||||
DeviceErrorPluginNotFound,
|
||||
DeviceErrorSetupFailed
|
||||
|
||||
@ -3,4 +3,4 @@ SUBDIRS += elro \
|
||||
intertechno \
|
||||
meisteranker \
|
||||
wifidetector \
|
||||
|
||||
# boblight \
|
||||
|
||||
62
server/jsonrpc/actionhandler.cpp
Normal file
62
server/jsonrpc/actionhandler.cpp
Normal file
@ -0,0 +1,62 @@
|
||||
#include "actionhandler.h"
|
||||
|
||||
#include "devicemanager.h"
|
||||
#include "hivecore.h"
|
||||
#include "action.h"
|
||||
|
||||
#include <QDebug>
|
||||
|
||||
ActionHandler::ActionHandler(QObject *parent) :
|
||||
JsonHandler(parent)
|
||||
{
|
||||
QVariantMap params;
|
||||
QVariantMap returns;
|
||||
|
||||
params.clear(); returns.clear();
|
||||
setDescription("ExecuteAction", "Execute a single action.");
|
||||
params.insert("actionTypeId", "uuid");
|
||||
params.insert("deviceId", "uuid");
|
||||
params.insert("params", JsonTypes::paramTypeRef());
|
||||
setParams("ExecuteAction", JsonTypes::actionDescription());
|
||||
returns.insert("success", "bool");
|
||||
returns.insert("errorMessage", "string");
|
||||
setReturns("ExecuteAction", returns);
|
||||
}
|
||||
|
||||
QString ActionHandler::name() const
|
||||
{
|
||||
return "Actions";
|
||||
}
|
||||
|
||||
QVariantMap ActionHandler::ExecuteAction(const QVariantMap ¶ms)
|
||||
{
|
||||
|
||||
QUuid deviceId = params.value("deviceId").toUuid();
|
||||
QUuid actionTypeId = params.value("actionTypeId").toUuid();
|
||||
QVariantMap actionParams = params.value("params").toMap();
|
||||
|
||||
Action action(deviceId, actionTypeId);
|
||||
action.setParams(actionParams);
|
||||
|
||||
qDebug() << "actions params in json" << action.params() << params;
|
||||
|
||||
|
||||
QVariantMap returns;
|
||||
DeviceManager::DeviceError error = HiveCore::instance()->deviceManager()->executeAction(action);
|
||||
|
||||
switch (error) {
|
||||
case DeviceManager::DeviceErrorNoError:
|
||||
returns.insert("success", true);
|
||||
returns.insert("errorMessage", "");
|
||||
break;
|
||||
case DeviceManager::DeviceErrorDeviceNotFound:
|
||||
returns.insert("errorMessage", "No such device");
|
||||
returns.insert("success", false);
|
||||
break;
|
||||
default:
|
||||
returns.insert("errorMessage", "Unknown error.");
|
||||
returns.insert("success", false);
|
||||
}
|
||||
|
||||
return returns;
|
||||
}
|
||||
17
server/jsonrpc/actionhandler.h
Normal file
17
server/jsonrpc/actionhandler.h
Normal file
@ -0,0 +1,17 @@
|
||||
#ifndef ACTIONHANDLER_H
|
||||
#define ACTIONHANDLER_H
|
||||
|
||||
#include "jsonhandler.h"
|
||||
|
||||
class ActionHandler : public JsonHandler
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit ActionHandler(QObject *parent = 0);
|
||||
|
||||
QString name() const;
|
||||
|
||||
Q_INVOKABLE QVariantMap ExecuteAction(const QVariantMap ¶ms);
|
||||
};
|
||||
|
||||
#endif // ACTIONHANDLER_H
|
||||
184
server/jsonrpc/devicehandler.cpp
Normal file
184
server/jsonrpc/devicehandler.cpp
Normal file
@ -0,0 +1,184 @@
|
||||
#include "devicehandler.h"
|
||||
|
||||
#include "deviceclass.h"
|
||||
#include "hivecore.h"
|
||||
#include "devicemanager.h"
|
||||
#include "deviceplugin.h"
|
||||
|
||||
DeviceHandler::DeviceHandler(QObject *parent) :
|
||||
JsonHandler(parent)
|
||||
{
|
||||
QVariantMap returns;
|
||||
QVariantMap params;
|
||||
|
||||
params.clear(); returns.clear();
|
||||
setDescription("GetSupportedDevices", "Returns a list of supported Device classes.");
|
||||
setParams("GetSupportedDevices", params);
|
||||
QVariantList deviceClasses;
|
||||
deviceClasses.append(JsonTypes::deviceClassRef());
|
||||
returns.insert("deviceClasses", deviceClasses);
|
||||
setReturns("GetSupportedDevices", returns);
|
||||
|
||||
|
||||
params.clear(); returns.clear();
|
||||
setDescription("GetPlugins", "Returns a list of loaded plugins.");
|
||||
setParams("GetPlugins", params);
|
||||
QVariantList plugins;
|
||||
plugins.append(JsonTypes::pluginTypeRef());
|
||||
returns.insert("plugins", plugins);
|
||||
setReturns("GetPlugins", returns);
|
||||
|
||||
params.clear(); returns.clear();
|
||||
setDescription("SetPluginParams", "Set a plugin's params.");
|
||||
params.insert("pluginId", "uuid");
|
||||
QVariantList pluginParams;
|
||||
pluginParams.append(JsonTypes::paramTypeRef());
|
||||
params.insert("pluginParams", pluginParams);
|
||||
setParams("SetPluginParams", params);
|
||||
setReturns("SetPluginParams", returns);
|
||||
|
||||
params.clear(); returns.clear();
|
||||
setDescription("AddConfiguredDevice", "Add a configured device.");
|
||||
params.insert("deviceClassId", "uuid");
|
||||
QVariantList deviceParams;
|
||||
deviceParams.append(JsonTypes::paramRef());
|
||||
params.insert("deviceParams", deviceParams);
|
||||
setParams("AddConfiguredDevice", params);
|
||||
returns.insert("success", "bool");
|
||||
returns.insert("errorMessage", "string");
|
||||
setReturns("AddConfiguredDevice", returns);
|
||||
|
||||
params.clear(); returns.clear();
|
||||
setDescription("GetConfiguredDevices", "Returns a list of configured devices.");
|
||||
setParams("GetConfiguredDevices", params);
|
||||
QVariantList devices;
|
||||
devices.append(JsonTypes::deviceRef());
|
||||
returns.insert("devices", devices);
|
||||
setReturns("GetConfiguredDevices", returns);
|
||||
|
||||
params.clear(); returns.clear();
|
||||
setDescription("GetTriggerTypes", "Get trigger types for a specified deviceClassId.");
|
||||
params.insert("deviceClassId", "uuid");
|
||||
setParams("GetTriggerTypes", params);
|
||||
QVariantList triggers;
|
||||
triggers.append(JsonTypes::triggerTypeRef());
|
||||
returns.insert("triggerTypes", triggers);
|
||||
setReturns("GetTriggerTypes", returns);
|
||||
|
||||
params.clear(); returns.clear();
|
||||
setDescription("GetActionTypes", "Get action types for a specified deviceClassId.");
|
||||
params.insert("deviceClassId", "uuid");
|
||||
setParams("GetActionTypes", params);
|
||||
QVariantList actions;
|
||||
actions.append(JsonTypes::actionTypeRef());
|
||||
returns.insert("actionTypes", actions);
|
||||
setReturns("GetActionTypes", returns);
|
||||
}
|
||||
|
||||
QString DeviceHandler::name() const
|
||||
{
|
||||
return "Devices";
|
||||
}
|
||||
|
||||
QVariantMap DeviceHandler::GetSupportedDevices(const QVariantMap ¶ms) const
|
||||
{
|
||||
Q_UNUSED(params)
|
||||
QVariantMap returns;
|
||||
QVariantList supportedDeviceList;
|
||||
foreach (const DeviceClass &deviceClass, HiveCore::instance()->deviceManager()->supportedDevices()) {
|
||||
supportedDeviceList.append(JsonTypes::packDeviceClass(deviceClass));
|
||||
}
|
||||
returns.insert("deviceClasses", supportedDeviceList);
|
||||
return returns;
|
||||
}
|
||||
|
||||
QVariantMap DeviceHandler::GetPlugins(const QVariantMap ¶ms) const
|
||||
{
|
||||
Q_UNUSED(params)
|
||||
QVariantMap returns;
|
||||
QVariantList plugins;
|
||||
foreach (DevicePlugin *plugin, HiveCore::instance()->deviceManager()->plugins()) {
|
||||
QVariantMap pluginMap;
|
||||
pluginMap.insert("id", plugin->pluginId());
|
||||
pluginMap.insert("name", plugin->pluginName());
|
||||
pluginMap.insert("params", plugin->configuration());
|
||||
plugins.append(pluginMap);
|
||||
}
|
||||
returns.insert("plugins", plugins);
|
||||
return returns;
|
||||
}
|
||||
|
||||
QVariantMap DeviceHandler::SetPluginParams(const QVariantMap ¶ms)
|
||||
{
|
||||
QUuid pluginId = params.value("pluginId").toUuid();
|
||||
QVariantMap pluginParams = params.value("pluginParams").toMap();
|
||||
HiveCore::instance()->deviceManager()->plugin(pluginId)->setConfiguration(pluginParams);
|
||||
return QVariantMap();
|
||||
}
|
||||
|
||||
QVariantMap DeviceHandler::AddConfiguredDevice(const QVariantMap ¶ms)
|
||||
{
|
||||
QUuid deviceClass = params.value("deviceClassId").toUuid();
|
||||
QVariantMap deviceParams = params.value("deviceParams").toMap();
|
||||
DeviceManager::DeviceError status = HiveCore::instance()->deviceManager()->addConfiguredDevice(deviceClass, deviceParams);
|
||||
QVariantMap returns;
|
||||
switch(status) {
|
||||
case DeviceManager::DeviceErrorNoError:
|
||||
returns.insert("success", true);
|
||||
break;
|
||||
case DeviceManager::DeviceErrorDeviceClassNotFound:
|
||||
returns.insert("errorMessage", "Error creating device. Device class not found.");
|
||||
returns.insert("success", false);
|
||||
break;
|
||||
case DeviceManager::DeviceErrorMissingParameter:
|
||||
returns.insert("errorMessage", "Error creating device. Missing parameter.");
|
||||
returns.insert("success", false);
|
||||
break;
|
||||
case DeviceManager::DeviceErrorSetupFailed:
|
||||
returns.insert("errorMessage", "Error creating device. Device setup failed.");
|
||||
returns.insert("success", false);
|
||||
break;
|
||||
default:
|
||||
returns.insert("errorMessage", "Unknown error.");
|
||||
returns.insert("success", false);
|
||||
}
|
||||
return returns;
|
||||
}
|
||||
|
||||
QVariantMap DeviceHandler::GetConfiguredDevices(const QVariantMap ¶ms) const
|
||||
{
|
||||
Q_UNUSED(params)
|
||||
QVariantMap returns;
|
||||
QVariantList configuredDeviceList;
|
||||
foreach (Device *device, HiveCore::instance()->deviceManager()->configuredDevices()) {
|
||||
configuredDeviceList.append(JsonTypes::packDevice(device));
|
||||
}
|
||||
returns.insert("devices", configuredDeviceList);
|
||||
return returns;
|
||||
}
|
||||
|
||||
QVariantMap DeviceHandler::GetTriggerTypes(const QVariantMap ¶ms) const
|
||||
{
|
||||
QVariantMap returns;
|
||||
|
||||
QVariantList triggerList;
|
||||
DeviceClass deviceClass = HiveCore::instance()->deviceManager()->findDeviceClass(params.value("deviceClassId").toUuid());
|
||||
foreach (const TriggerType &triggerType, deviceClass.triggers()) {
|
||||
triggerList.append(JsonTypes::packTriggerType(triggerType));
|
||||
}
|
||||
returns.insert("triggerTypes", triggerList);
|
||||
return returns;
|
||||
}
|
||||
|
||||
QVariantMap DeviceHandler::GetActionTypes(const QVariantMap ¶ms) const
|
||||
{
|
||||
QVariantMap returns;
|
||||
|
||||
QVariantList actionList;
|
||||
DeviceClass deviceClass = HiveCore::instance()->deviceManager()->findDeviceClass(params.value("deviceClassId").toUuid());
|
||||
foreach (const ActionType &actionType, deviceClass.actions()) {
|
||||
actionList.append(JsonTypes::packActionType(actionType));
|
||||
}
|
||||
returns.insert("actionTypes", actionList);
|
||||
return returns;
|
||||
}
|
||||
30
server/jsonrpc/devicehandler.h
Normal file
30
server/jsonrpc/devicehandler.h
Normal file
@ -0,0 +1,30 @@
|
||||
#ifndef DEVICEHANDLER_H
|
||||
#define DEVICEHANDLER_H
|
||||
|
||||
#include "jsonhandler.h"
|
||||
|
||||
class DeviceHandler : public JsonHandler
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit DeviceHandler(QObject *parent = 0);
|
||||
|
||||
QString name() const override;
|
||||
|
||||
Q_INVOKABLE QVariantMap GetSupportedDevices(const QVariantMap ¶ms) const;
|
||||
|
||||
Q_INVOKABLE QVariantMap GetPlugins(const QVariantMap ¶ms) const;
|
||||
|
||||
Q_INVOKABLE QVariantMap SetPluginParams(const QVariantMap ¶ms);
|
||||
|
||||
Q_INVOKABLE QVariantMap AddConfiguredDevice(const QVariantMap ¶ms);
|
||||
|
||||
Q_INVOKABLE QVariantMap GetConfiguredDevices(const QVariantMap ¶ms) const;
|
||||
|
||||
Q_INVOKABLE QVariantMap GetTriggerTypes(const QVariantMap ¶ms) const;
|
||||
|
||||
Q_INVOKABLE QVariantMap GetActionTypes(const QVariantMap ¶ms) const;
|
||||
|
||||
};
|
||||
|
||||
#endif // DEVICEHANDLER_H
|
||||
81
server/jsonrpc/jsonhandler.cpp
Normal file
81
server/jsonrpc/jsonhandler.cpp
Normal file
@ -0,0 +1,81 @@
|
||||
#include "jsonhandler.h"
|
||||
|
||||
#include <QMetaMethod>
|
||||
#include <QDebug>
|
||||
|
||||
JsonHandler::JsonHandler(QObject *parent) :
|
||||
QObject(parent)
|
||||
{
|
||||
}
|
||||
|
||||
QVariantMap JsonHandler::introspect()
|
||||
{
|
||||
QVariantMap data;
|
||||
for (int i = 0; i < metaObject()->methodCount(); ++i) {
|
||||
QMetaMethod method = metaObject()->method(i);
|
||||
if (method.methodType() == QMetaMethod::Method) {
|
||||
QVariantMap methodData;
|
||||
if (!m_descriptions.contains(method.name()) || !m_params.contains(method.name()) || !m_returns.contains(method.name())) {
|
||||
continue;
|
||||
}
|
||||
methodData.insert("description", m_descriptions.value(method.name()));
|
||||
methodData.insert("params", m_params.value(method.name()));
|
||||
methodData.insert("returns", m_returns.value(method.name()));
|
||||
data.insert(name() + "." + method.name(), methodData);
|
||||
}
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
bool JsonHandler::hasMethod(const QString &methodName)
|
||||
{
|
||||
return m_descriptions.contains(methodName) && m_params.contains(methodName) && m_returns.contains(methodName);
|
||||
}
|
||||
|
||||
bool JsonHandler::validateParams(const QString &methodName, const QVariantMap ¶ms)
|
||||
{
|
||||
QVariantMap paramTemplate = m_params.value(methodName);
|
||||
return JsonTypes::validateMap(paramTemplate, params);
|
||||
}
|
||||
|
||||
bool JsonHandler::validateReturns(const QString &methodName, const QVariantMap &returns)
|
||||
{
|
||||
QVariantMap returnsTemplate = m_returns.value(methodName);
|
||||
return JsonTypes::validateMap(returnsTemplate, returns);
|
||||
}
|
||||
|
||||
void JsonHandler::setDescription(const QString &methodName, const QString &description)
|
||||
{
|
||||
for(int i = 0; i < metaObject()->methodCount(); ++i) {
|
||||
QMetaMethod method = metaObject()->method(i);
|
||||
if (method.name() == methodName) {
|
||||
m_descriptions.insert(methodName, description);
|
||||
return;
|
||||
}
|
||||
}
|
||||
qWarning() << "Cannot set description. No such method:" << methodName;
|
||||
}
|
||||
|
||||
void JsonHandler::setParams(const QString &methodName, const QVariantMap ¶ms)
|
||||
{
|
||||
for(int i = 0; i < metaObject()->methodCount(); ++i) {
|
||||
QMetaMethod method = metaObject()->method(i);
|
||||
if (method.name() == methodName) {
|
||||
m_params.insert(methodName, params);
|
||||
return;
|
||||
}
|
||||
}
|
||||
qWarning() << "Cannot set params. No such method:" << methodName;
|
||||
}
|
||||
|
||||
void JsonHandler::setReturns(const QString &methodName, const QVariantMap &returns)
|
||||
{
|
||||
for(int i = 0; i < metaObject()->methodCount(); ++i) {
|
||||
QMetaMethod method = metaObject()->method(i);
|
||||
if (method.name() == methodName) {
|
||||
m_returns.insert(methodName, returns);
|
||||
return;
|
||||
}
|
||||
}
|
||||
qWarning() << "Cannot set returns. No such method:" << methodName;
|
||||
}
|
||||
34
server/jsonrpc/jsonhandler.h
Normal file
34
server/jsonrpc/jsonhandler.h
Normal file
@ -0,0 +1,34 @@
|
||||
#ifndef JSONHANDLER_H
|
||||
#define JSONHANDLER_H
|
||||
|
||||
#include "jsontypes.h"
|
||||
|
||||
#include <QObject>
|
||||
#include <QVariantMap>
|
||||
|
||||
class JsonHandler : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit JsonHandler(QObject *parent = 0);
|
||||
|
||||
virtual QString name() const = 0;
|
||||
|
||||
QVariantMap introspect();
|
||||
|
||||
bool hasMethod(const QString &methodName);
|
||||
bool validateParams(const QString &methodName, const QVariantMap ¶ms);
|
||||
bool validateReturns(const QString &methodName, const QVariantMap &returns);
|
||||
|
||||
protected:
|
||||
void setDescription(const QString &methodName, const QString &description);
|
||||
void setParams(const QString &methodName, const QVariantMap ¶ms);
|
||||
void setReturns(const QString &methodName, const QVariantMap &returns);
|
||||
|
||||
private:
|
||||
QHash<QString, QString> m_descriptions;
|
||||
QHash<QString, QVariantMap> m_params;
|
||||
QHash<QString, QVariantMap> m_returns;
|
||||
};
|
||||
|
||||
#endif // JSONHANDLER_H
|
||||
128
server/jsonrpc/jsonrpcserver.cpp
Normal file
128
server/jsonrpc/jsonrpcserver.cpp
Normal file
@ -0,0 +1,128 @@
|
||||
#include "jsonrpcserver.h"
|
||||
#include "jsontypes.h"
|
||||
|
||||
#include "tcpserver.h"
|
||||
#include "jsonhandler.h"
|
||||
|
||||
#include "hivecore.h"
|
||||
#include "devicemanager.h"
|
||||
#include "deviceplugin.h"
|
||||
#include "deviceclass.h"
|
||||
#include "device.h"
|
||||
#include "rule.h"
|
||||
#include "ruleengine.h"
|
||||
|
||||
#include "devicehandler.h"
|
||||
#include "actionhandler.h"
|
||||
#include "ruleshandler.h"
|
||||
|
||||
#include <QJsonDocument>
|
||||
#include <QStringList>
|
||||
|
||||
JsonRPCServer::JsonRPCServer(QObject *parent):
|
||||
QObject(parent),
|
||||
m_tcpServer(new TcpServer(this))
|
||||
{
|
||||
connect(m_tcpServer, &TcpServer::jsonDataAvailable, this, &JsonRPCServer::processData);
|
||||
m_tcpServer->startServer();
|
||||
|
||||
|
||||
registerHandler(new DeviceHandler(this));
|
||||
registerHandler(new ActionHandler(this));
|
||||
registerHandler(new RulesHandler(this));
|
||||
}
|
||||
|
||||
void JsonRPCServer::processData(int clientId, const QByteArray &jsonData)
|
||||
{
|
||||
QJsonParseError error;
|
||||
QJsonDocument jsonDoc = QJsonDocument::fromJson(jsonData, &error);
|
||||
|
||||
if(error.error != QJsonParseError::NoError) {
|
||||
qDebug() << "failed to parse data" << jsonData << ":" << error.errorString();
|
||||
}
|
||||
qDebug() << "-------------------------\n" << jsonDoc.toJson();
|
||||
|
||||
QVariantMap message = jsonDoc.toVariant().toMap();
|
||||
|
||||
bool success;
|
||||
int commandId = message.value("id").toInt(&success);
|
||||
if (!success) {
|
||||
qWarning() << "Error parsing command. Missing \"id\":" << jsonData;
|
||||
return;
|
||||
}
|
||||
|
||||
QStringList commandList = message.value("method").toString().split('.');
|
||||
if (commandList.count() != 2) {
|
||||
qWarning() << "Error parsing method.\nGot:" << message.value("method").toString() << "\nExpected: \"Namespace.method\"";
|
||||
return;
|
||||
}
|
||||
|
||||
QString targetNamespace = commandList.first();
|
||||
QString method = commandList.last();
|
||||
QVariantMap params = message.value("params").toMap();
|
||||
|
||||
qDebug() << "got:" << targetNamespace << method << params;
|
||||
emit commandReceived(targetNamespace, method, params);
|
||||
|
||||
if (targetNamespace == "JSONRPC") {
|
||||
if (method == "Introspect") {
|
||||
QVariantMap data;
|
||||
data.insert("types", JsonTypes::allTypes());
|
||||
QVariantMap methods;
|
||||
foreach (JsonHandler *handler, m_handlers) {
|
||||
qDebug() << "got handler" << handler->name() << handler->introspect();
|
||||
methods.unite(handler->introspect());
|
||||
}
|
||||
data.insert("methods", methods);
|
||||
sendResponse(clientId, commandId, data);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
JsonHandler *handler = m_handlers.value(targetNamespace);
|
||||
if (!handler) {
|
||||
sendErrorResponse(clientId, commandId, "No such namespace");
|
||||
return;
|
||||
}
|
||||
if (!handler->hasMethod(method)) {
|
||||
sendErrorResponse(clientId, commandId, "No such method");
|
||||
return;
|
||||
}
|
||||
if (!handler->validateParams(method, params)) {
|
||||
sendErrorResponse(clientId, commandId, "Invalid params");
|
||||
return;
|
||||
}
|
||||
QVariantMap returns;
|
||||
QMetaObject::invokeMethod(handler, method.toLatin1().data(), Q_RETURN_ARG(QVariantMap, returns), Q_ARG(QVariantMap, params));
|
||||
Q_ASSERT(handler->validateReturns(method, returns));
|
||||
sendResponse(clientId, commandId, returns);
|
||||
}
|
||||
|
||||
void JsonRPCServer::registerHandler(JsonHandler *handler)
|
||||
{
|
||||
m_handlers.insert(handler->name(), handler);
|
||||
}
|
||||
|
||||
void JsonRPCServer::sendResponse(int clientId, int commandId, const QVariantMap ¶ms)
|
||||
{
|
||||
QVariantMap rsp;
|
||||
rsp.insert("id", commandId);
|
||||
rsp.insert("status", "success");
|
||||
rsp.insert("params", params);
|
||||
|
||||
QJsonDocument jsonDoc = QJsonDocument::fromVariant(rsp);
|
||||
m_tcpServer->sendResponse(clientId, jsonDoc.toJson());
|
||||
}
|
||||
|
||||
void JsonRPCServer::sendErrorResponse(int clientId, int commandId, const QString &error)
|
||||
{
|
||||
QVariantMap rsp;
|
||||
rsp.insert("id", commandId);
|
||||
rsp.insert("status", "error");
|
||||
rsp.insert("error", error);
|
||||
|
||||
QJsonDocument jsonDoc = QJsonDocument::fromVariant(rsp);
|
||||
m_tcpServer->sendResponse(clientId, jsonDoc.toJson());
|
||||
}
|
||||
|
||||
|
||||
@ -11,6 +11,7 @@
|
||||
|
||||
class TcpServer;
|
||||
class Device;
|
||||
class JsonHandler;
|
||||
|
||||
class JsonRPCServer: public QObject
|
||||
{
|
||||
@ -25,20 +26,14 @@ private slots:
|
||||
void processData(int clientId, const QByteArray &jsonData);
|
||||
|
||||
private:
|
||||
void handleDevicesMessage(int clientId, int commandId, const QString &method, const QVariantMap ¶ms);
|
||||
void handleRulesMessage(int clientId, int commandId, const QString &method, const QVariantMap ¶ms);
|
||||
void handleActionMessage(int clientId, int commandId, const QString &method, const QVariantMap ¶ms);
|
||||
|
||||
QVariantMap packDeviceClass(const DeviceClass &deviceClass);
|
||||
QVariantMap packDevice(Device *device);
|
||||
QVariantMap packTrigger(const Trigger &action);
|
||||
QVariantMap packAction(const Action &action);
|
||||
void registerHandler(JsonHandler *handler);
|
||||
|
||||
void sendResponse(int clientId, int commandId, const QVariantMap ¶ms = QVariantMap());
|
||||
void sendErrorResponse(int clientId, int commandId, const QString &error);
|
||||
|
||||
private:
|
||||
TcpServer *m_tcpServer;
|
||||
QHash<QString, JsonHandler*> m_handlers;
|
||||
};
|
||||
|
||||
#endif
|
||||
449
server/jsonrpc/jsontypes.cpp
Normal file
449
server/jsonrpc/jsontypes.cpp
Normal file
@ -0,0 +1,449 @@
|
||||
#include "jsontypes.h"
|
||||
|
||||
#include "device.h"
|
||||
|
||||
#include <QDebug>
|
||||
|
||||
namespace JsonTypes {
|
||||
|
||||
QVariantMap allTypes()
|
||||
{
|
||||
QVariantMap allTypes;
|
||||
allTypes.insert("BasicType", basicTypes());
|
||||
allTypes.insert("ParamType", paramTypeDescription());
|
||||
allTypes.insert("StateType", stateTypeDescription());
|
||||
allTypes.insert("TriggerType", triggerTypeDescription());
|
||||
allTypes.insert("ActionType", actionTypeDescription());
|
||||
allTypes.insert("DeviceClass", deviceClassDescription());
|
||||
allTypes.insert("PluginType", pluginTypeDescription());
|
||||
allTypes.insert("Param", paramDescription());
|
||||
allTypes.insert("Trigger", triggerDescription());
|
||||
allTypes.insert("Device", deviceDescription());
|
||||
allTypes.insert("Action", actionDescription());
|
||||
return allTypes;
|
||||
}
|
||||
|
||||
QString basicTypesRef()
|
||||
{
|
||||
return "$ref:BasicType";
|
||||
}
|
||||
|
||||
QVariantList basicTypes()
|
||||
{
|
||||
QVariantList basicTypes;
|
||||
basicTypes.append("uuid");
|
||||
basicTypes.append("string");
|
||||
basicTypes.append("integer");
|
||||
basicTypes.append("double");
|
||||
basicTypes.append("bool");
|
||||
return basicTypes;
|
||||
}
|
||||
|
||||
QString paramTypeRef()
|
||||
{
|
||||
return "$ref:ParamType";
|
||||
}
|
||||
|
||||
QVariantMap paramTypeDescription()
|
||||
{
|
||||
QVariantMap paramType;
|
||||
paramType.insert("name", "string");
|
||||
paramType.insert("type", basicTypesRef());
|
||||
// paramType.insert("default", "value");
|
||||
// paramType.insert("value", "value");
|
||||
return paramType;
|
||||
}
|
||||
|
||||
QString paramRef()
|
||||
{
|
||||
return "$ref:Param";
|
||||
}
|
||||
|
||||
QVariantMap paramDescription()
|
||||
{
|
||||
QVariantMap param;
|
||||
param.insert("name", "string");
|
||||
param.insert("value", basicTypesRef());
|
||||
return param;
|
||||
}
|
||||
|
||||
QString stateTypeRef()
|
||||
{
|
||||
return "$ref:StateType";
|
||||
}
|
||||
|
||||
QVariantMap stateTypeDescription()
|
||||
{
|
||||
QVariantMap stateTypeDescription;
|
||||
stateTypeDescription.insert("id", "uuid");
|
||||
stateTypeDescription.insert("name", "string");
|
||||
stateTypeDescription.insert("type", basicTypesRef());
|
||||
// stateTypeDescription.insert("default", "value");
|
||||
return stateTypeDescription;
|
||||
}
|
||||
|
||||
QString triggerTypeRef()
|
||||
{
|
||||
return "$ref:TriggerType";
|
||||
}
|
||||
|
||||
QVariantMap triggerTypeDescription()
|
||||
{
|
||||
QVariantMap triggerTypeDescription;
|
||||
triggerTypeDescription.insert("id", "uuid");
|
||||
triggerTypeDescription.insert("name", "string");
|
||||
QVariantList params;
|
||||
params.append(paramTypeRef());
|
||||
triggerTypeDescription.insert("params", params);
|
||||
return triggerTypeDescription;
|
||||
}
|
||||
|
||||
QVariantMap packTriggerType(const TriggerType &triggerType)
|
||||
{
|
||||
QVariantMap variant;
|
||||
variant.insert("id", triggerType.id());
|
||||
variant.insert("name", triggerType.name());
|
||||
variant.insert("params", triggerType.parameters());
|
||||
return variant;
|
||||
}
|
||||
|
||||
QString triggerRef()
|
||||
{
|
||||
return "$ref:Trigger";
|
||||
}
|
||||
|
||||
QVariantMap triggerDescription()
|
||||
{
|
||||
QVariantMap triggerDescription;
|
||||
triggerDescription.insert("triggerTypeId", "uuid");
|
||||
triggerDescription.insert("deviceId", "uuid");
|
||||
QVariantList params;
|
||||
params.append(paramRef());
|
||||
triggerDescription.insert("params", params);
|
||||
return triggerDescription;
|
||||
}
|
||||
|
||||
QVariantMap packTrigger(const Trigger &trigger)
|
||||
{
|
||||
QVariantMap variant;
|
||||
variant.insert("id", trigger.triggerTypeId());
|
||||
variant.insert("deviceId", trigger.deviceId());
|
||||
variant.insert("params", trigger.params());
|
||||
return variant;
|
||||
}
|
||||
|
||||
QString actionTypeRef()
|
||||
{
|
||||
return "$ref:ActionType";
|
||||
}
|
||||
|
||||
QVariantMap actionTypeDescription()
|
||||
{
|
||||
QVariantMap actionTypeDescription;
|
||||
actionTypeDescription.insert("id", "uuid");
|
||||
actionTypeDescription.insert("name", "string");
|
||||
QVariantList params;
|
||||
params.append(paramTypeRef());
|
||||
actionTypeDescription.insert("params", params);
|
||||
return actionTypeDescription;
|
||||
}
|
||||
|
||||
QVariantMap packActionType(const ActionType &actionType)
|
||||
{
|
||||
QVariantMap variantMap;
|
||||
variantMap.insert("id", actionType.id());
|
||||
variantMap.insert("name", actionType.name());
|
||||
variantMap.insert("params", actionType.parameters());
|
||||
return variantMap;
|
||||
}
|
||||
|
||||
QString actionRef()
|
||||
{
|
||||
return "$ref:Action";
|
||||
}
|
||||
|
||||
QVariantMap actionDescription()
|
||||
{
|
||||
QVariantMap actionDescription;
|
||||
actionDescription.insert("actionTypeId", "uuid");
|
||||
actionDescription.insert("deviceId", "uuid");
|
||||
QVariantList params;
|
||||
params.append(paramRef());
|
||||
actionDescription.insert("params", params);
|
||||
return actionDescription;
|
||||
}
|
||||
|
||||
QVariantMap packAction(const Action &action)
|
||||
{
|
||||
QVariantMap variant;
|
||||
variant.insert("actionTypeId", action.actionTypeId());
|
||||
variant.insert("deviceId", action.deviceId());
|
||||
variant.insert("params", action.params());
|
||||
return variant;
|
||||
}
|
||||
|
||||
QString deviceClassRef()
|
||||
{
|
||||
return "$ref:DeviceClass";
|
||||
}
|
||||
|
||||
QVariantMap deviceClassDescription()
|
||||
{
|
||||
QVariantMap deviceClass;
|
||||
deviceClass.insert("id", "uuid");
|
||||
deviceClass.insert("name", "string");
|
||||
QVariantList states;
|
||||
states.append(stateTypeRef());
|
||||
deviceClass.insert("states", states);
|
||||
QVariantList triggers;
|
||||
triggers.append(triggerTypeRef());
|
||||
deviceClass.insert("triggers", triggers);
|
||||
QVariantList actions;
|
||||
actions.append(actionTypeRef());
|
||||
deviceClass.insert("actions", actions);
|
||||
QVariantList params;
|
||||
params.append(paramTypeRef());
|
||||
deviceClass.insert("params", params);
|
||||
return deviceClass;
|
||||
}
|
||||
|
||||
QVariantMap packDeviceClass(const DeviceClass &deviceClass)
|
||||
{
|
||||
QVariantMap variant;
|
||||
variant.insert("name", deviceClass.name());
|
||||
variant.insert("id", deviceClass.id());
|
||||
QVariantList stateTypes;
|
||||
foreach (const StateType &stateType, deviceClass.states()) {
|
||||
QVariantMap stateMap;
|
||||
stateMap.insert("id", stateType.id().toString());
|
||||
stateMap.insert("name", stateType.name());
|
||||
stateMap.insert("type", QVariant::typeToName(stateType.type()));
|
||||
|
||||
stateTypes.append(stateMap);
|
||||
}
|
||||
QVariantList triggerTypes;
|
||||
foreach (const TriggerType &triggerType, deviceClass.triggers()) {
|
||||
QVariantMap triggerMap;
|
||||
triggerMap.insert("id", triggerType.id().toString());
|
||||
triggerMap.insert("name", triggerType.name());
|
||||
triggerMap.insert("params", triggerType.parameters());
|
||||
|
||||
triggerTypes.append(triggerMap);
|
||||
}
|
||||
QVariantList actionTypes;
|
||||
foreach (const ActionType &actionType, deviceClass.actions()) {
|
||||
QVariantMap actionMap;
|
||||
actionMap.insert("id", actionType.id().toString());
|
||||
actionMap.insert("name", actionType.name());
|
||||
actionMap.insert("params", actionType.parameters());
|
||||
|
||||
actionTypes.append(actionMap);
|
||||
}
|
||||
variant.insert("params", deviceClass.params());
|
||||
variant.insert("states", stateTypes);
|
||||
variant.insert("triggers", triggerTypes);
|
||||
variant.insert("actions", actionTypes);
|
||||
return variant;
|
||||
}
|
||||
|
||||
QString pluginTypeRef()
|
||||
{
|
||||
return "$ref:PluginType";
|
||||
}
|
||||
|
||||
QVariantMap pluginTypeDescription()
|
||||
{
|
||||
QVariantMap pluginDescription;
|
||||
pluginDescription.insert("id", "uuid");
|
||||
pluginDescription.insert("name", "string");
|
||||
QVariantList params;
|
||||
params.append(paramTypeRef());
|
||||
pluginDescription.insert("params", params);
|
||||
return pluginDescription;
|
||||
}
|
||||
|
||||
QVariantMap packPlugin(DevicePlugin *plugin)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
QString deviceRef()
|
||||
{
|
||||
return "$ref:Device";
|
||||
}
|
||||
|
||||
QVariantMap deviceDescription()
|
||||
{
|
||||
QVariantMap deviceDescription;
|
||||
deviceDescription.insert("id", "uuid");
|
||||
deviceDescription.insert("deviceClassId", "uuid");
|
||||
deviceDescription.insert("name", "string");
|
||||
QVariantList params;
|
||||
params.append(paramRef());
|
||||
deviceDescription.insert("params", params);
|
||||
return deviceDescription;
|
||||
}
|
||||
|
||||
QVariantMap packDevice(Device *device)
|
||||
{
|
||||
QVariantMap variant;
|
||||
variant.insert("id", device->id());
|
||||
variant.insert("deviceClassId", device->deviceClassId());
|
||||
variant.insert("name", device->name());
|
||||
variant.insert("params", device->params());
|
||||
return variant;
|
||||
}
|
||||
|
||||
bool validateMap(const QVariantMap &templateMap, const QVariantMap &map)
|
||||
{
|
||||
foreach (const QString &key, templateMap.keys()) {
|
||||
if (!map.contains(key)) {
|
||||
qDebug() << "missing key" << key << templateMap << map;
|
||||
return false;
|
||||
}
|
||||
if (!validateVariant(templateMap.value(key), map.value(key))) {
|
||||
qDebug() << "Object not matching template";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool validateProperty(const QVariant &templateValue, const QVariant &value)
|
||||
{
|
||||
if (templateValue == "uuid") {
|
||||
return value.canConvert(QVariant::Uuid);
|
||||
}
|
||||
if (templateValue == "string") {
|
||||
return value.canConvert(QVariant::String);
|
||||
}
|
||||
if (templateValue == "bool") {
|
||||
return value.canConvert(QVariant::Bool);
|
||||
}
|
||||
qWarning() << "Unhandled property type!" << templateValue;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool validateList(const QVariantList &templateList, const QVariantList &list)
|
||||
{
|
||||
Q_ASSERT(templateList.count() == 1);
|
||||
QVariant entryTemplate = templateList.first();
|
||||
|
||||
qDebug() << "validating list" << templateList;
|
||||
|
||||
for (int i = 0; i < list.count(); ++i) {
|
||||
QVariant listEntry = list.at(i);
|
||||
if (!validateVariant(entryTemplate, listEntry)) {
|
||||
qDebug() << "List entry not matching template";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool validateVariant(const QVariant &templateVariant, const QVariant &variant)
|
||||
{
|
||||
switch(templateVariant.type()) {
|
||||
case QVariant::String:
|
||||
if (templateVariant.toString().startsWith("$ref:")) {
|
||||
QString refName = templateVariant.toString();
|
||||
if (refName == JsonTypes::actionRef()) {
|
||||
qDebug() << "validating action";
|
||||
if (!validateMap(actionDescription(), variant.toMap())) {
|
||||
qDebug() << "Error validating action";
|
||||
return false;
|
||||
}
|
||||
} else if (refName == JsonTypes::triggerRef()) {
|
||||
if (!validateMap(triggerDescription(), variant.toMap())) {
|
||||
qDebug() << "trigger not valid";
|
||||
return false;
|
||||
}
|
||||
} else if (refName == deviceRef()) {
|
||||
if (!validateMap(deviceDescription(), variant.toMap())) {
|
||||
qDebug() << "device not valid";
|
||||
return false;
|
||||
}
|
||||
} else if (refName == deviceClassRef()) {
|
||||
if (!validateMap(deviceClassDescription(), variant.toMap())) {
|
||||
qDebug() << "device class not valid";
|
||||
return false;
|
||||
}
|
||||
} else if (refName == paramTypeRef()) {
|
||||
if (!validateMap(paramTypeDescription(), variant.toMap())) {
|
||||
qDebug() << "param types not matching";
|
||||
return false;
|
||||
}
|
||||
} else if (refName == actionTypeRef()) {
|
||||
if (!validateMap(actionTypeDescription(), variant.toMap())) {
|
||||
qDebug() << "action type not matching";
|
||||
return false;
|
||||
}
|
||||
} else if (refName == triggerTypeRef()) {
|
||||
if (!validateMap(triggerTypeDescription(), variant.toMap())) {
|
||||
qDebug() << "trigger type not matching";
|
||||
return false;
|
||||
}
|
||||
} else if (refName == stateTypeRef()) {
|
||||
if (!validateMap(stateTypeDescription(), variant.toMap())) {
|
||||
qDebug() << "state type not matching";
|
||||
return false;
|
||||
}
|
||||
} else if (refName == pluginTypeRef()) {
|
||||
if (!validateMap(pluginTypeDescription(), variant.toMap())) {
|
||||
qDebug() << "plugin type not matchint";
|
||||
return false;
|
||||
}
|
||||
} else if (refName == basicTypesRef()) {
|
||||
if (!validateBasicType(variant)) {
|
||||
qDebug() << "value not allowed in" << basicTypesRef();
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
qDebug() << "unhandled ref:" << refName;
|
||||
return false;
|
||||
}
|
||||
|
||||
} else {
|
||||
if (!JsonTypes::validateProperty(templateVariant, variant)) {
|
||||
qDebug() << "property not matching:" << templateVariant << "!=" << variant;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case QVariant::Map:
|
||||
if (!validateMap(templateVariant.toMap(), variant.toMap())) {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case QVariant::List:
|
||||
if (!validateList(templateVariant.toList(), variant.toList())) {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
qDebug() << "unhandled value" << templateVariant;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool validateBasicType(const QVariant &variant)
|
||||
{
|
||||
if (variant.canConvert(QVariant::Uuid)) {
|
||||
return true;
|
||||
}
|
||||
if (variant.canConvert(QVariant::String)) {
|
||||
return true;
|
||||
}
|
||||
if (variant.canConvert(QVariant::Int)) {
|
||||
return true;
|
||||
}
|
||||
if (variant.canConvert(QVariant::Double)) {
|
||||
return true;
|
||||
}
|
||||
if (variant.canConvert(QVariant::Bool)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
67
server/jsonrpc/jsontypes.h
Normal file
67
server/jsonrpc/jsontypes.h
Normal file
@ -0,0 +1,67 @@
|
||||
#ifndef JSONTYPES_H
|
||||
#define JSONTYPES_H
|
||||
|
||||
#include "deviceclass.h"
|
||||
#include "trigger.h"
|
||||
#include "action.h"
|
||||
#include "actiontype.h"
|
||||
|
||||
#include <QObject>
|
||||
|
||||
#include <QVariantMap>
|
||||
|
||||
class DevicePlugin;
|
||||
class Device;
|
||||
|
||||
namespace JsonTypes
|
||||
{
|
||||
QVariantMap allTypes();
|
||||
|
||||
QString basicTypesRef();
|
||||
QVariantList basicTypes();
|
||||
|
||||
QString paramTypeRef();
|
||||
QVariantMap paramTypeDescription();
|
||||
|
||||
QString paramRef();
|
||||
QVariantMap paramDescription();
|
||||
|
||||
QString stateTypeRef();
|
||||
QVariantMap stateTypeDescription();
|
||||
|
||||
QString triggerTypeRef();
|
||||
QVariantMap triggerTypeDescription();
|
||||
QVariantMap packTriggerType(const TriggerType &triggerType);
|
||||
|
||||
QString triggerRef();
|
||||
QVariantMap triggerDescription();
|
||||
QVariantMap packTrigger(const Trigger &trigger);
|
||||
|
||||
QString actionTypeRef();
|
||||
QVariantMap actionTypeDescription();
|
||||
QVariantMap packActionType(const ActionType &actionType);
|
||||
|
||||
QString actionRef();
|
||||
QVariantMap actionDescription();
|
||||
QVariantMap packAction(const Action &action);
|
||||
|
||||
QString deviceClassRef();
|
||||
QVariantMap deviceClassDescription();
|
||||
QVariantMap packDeviceClass(const DeviceClass &deviceClass);
|
||||
|
||||
QString pluginTypeRef();
|
||||
QVariantMap pluginTypeDescription();
|
||||
QVariantMap packPlugin(DevicePlugin *plugin);
|
||||
|
||||
QString deviceRef();
|
||||
QVariantMap deviceDescription();
|
||||
QVariantMap packDevice(Device *device);
|
||||
|
||||
bool validateMap(const QVariantMap &templateMap, const QVariantMap &map);
|
||||
bool validateProperty(const QVariant &templateValue, const QVariant &value);
|
||||
bool validateList(const QVariantList &templateList, const QVariantList &list);
|
||||
bool validateVariant(const QVariant &templateVariant, const QVariant &variant);
|
||||
bool validateBasicType(const QVariant &variant);
|
||||
}
|
||||
|
||||
#endif // JSONTYPES_H
|
||||
99
server/jsonrpc/ruleshandler.cpp
Normal file
99
server/jsonrpc/ruleshandler.cpp
Normal file
@ -0,0 +1,99 @@
|
||||
#include "ruleshandler.h"
|
||||
|
||||
#include "hivecore.h"
|
||||
#include "ruleengine.h"
|
||||
|
||||
#include <QDebug>
|
||||
|
||||
RulesHandler::RulesHandler(QObject *parent) :
|
||||
JsonHandler(parent)
|
||||
{
|
||||
QVariantMap params;
|
||||
QVariantMap returns;
|
||||
|
||||
params.clear(); returns.clear();
|
||||
setDescription("GetRules", "Get all configured rules");
|
||||
setParams("GetRules", params);
|
||||
setReturns("GetRules", returns);
|
||||
|
||||
params.clear(); returns.clear();
|
||||
setDescription("AddRule", "Add a rule");
|
||||
params.insert("trigger", JsonTypes::triggerRef());
|
||||
QVariantList actions;
|
||||
actions.append(JsonTypes::actionRef());
|
||||
params.insert("actions", actions);
|
||||
setParams("AddRule", params);
|
||||
setReturns("AddRule", returns);
|
||||
|
||||
}
|
||||
|
||||
QString RulesHandler::name() const
|
||||
{
|
||||
return "Rules";
|
||||
}
|
||||
|
||||
QVariantMap RulesHandler::GetRules(const QVariantMap ¶ms)
|
||||
{
|
||||
Q_UNUSED(params)
|
||||
|
||||
QVariantList rulesList;
|
||||
foreach (const Rule &rule, HiveCore::instance()->ruleEngine()->rules()) {
|
||||
qDebug() << "got rule" << rule.id();
|
||||
QVariantMap ruleMap;
|
||||
ruleMap.insert("id", rule.id());
|
||||
ruleMap.insert("trigger", JsonTypes::packTrigger(rule.trigger()));
|
||||
QVariantList actionList;
|
||||
foreach (const Action &action, rule.actions()) {
|
||||
actionList.append(JsonTypes::packAction(action));
|
||||
}
|
||||
|
||||
ruleMap.insert("actions", actionList);
|
||||
rulesList.append(ruleMap);
|
||||
}
|
||||
QVariantMap returns;
|
||||
returns.insert("rules", rulesList);
|
||||
|
||||
return returns;
|
||||
}
|
||||
|
||||
QVariantMap RulesHandler::AddRule(const QVariantMap ¶ms)
|
||||
{
|
||||
QVariantMap triggerMap = params.value("trigger").toMap();
|
||||
|
||||
QUuid triggerTypeId = triggerMap.value("triggerTypeId").toUuid();
|
||||
QUuid triggerDeviceId = triggerMap.value("deviceId").toUuid();
|
||||
QVariantMap triggerParams = triggerMap.value("params").toMap();
|
||||
Trigger trigger(triggerTypeId, triggerDeviceId, triggerParams);
|
||||
|
||||
QList<Action> actions;
|
||||
QVariantList actionList = params.value("actions").toList();
|
||||
qDebug() << "got action list" << actionList.count();
|
||||
foreach (const QVariant &actionVariant, actionList) {
|
||||
QVariantMap actionMap = actionVariant.toMap();
|
||||
Action action(actionMap.value("deviceId").toUuid(), actionMap.value("actionTypeId").toUuid());
|
||||
action.setParams(actionMap.value("params").toMap());
|
||||
actions.append(action);
|
||||
}
|
||||
|
||||
QVariantMap returns;
|
||||
if (actions.count() == 0) {
|
||||
returns.insert("success", false);
|
||||
returns.insert("errorMessage", "Missing parameter: \"actions\".");
|
||||
return returns;
|
||||
}
|
||||
|
||||
switch(HiveCore::instance()->ruleEngine()->addRule(trigger, actions)) {
|
||||
case RuleEngine::RuleErrorNoError:
|
||||
returns.insert("success", true);
|
||||
break;
|
||||
case RuleEngine::RuleErrorDeviceNotFound:
|
||||
returns.insert("success", false);
|
||||
returns.insert("errorMessage", "No such device.");
|
||||
break;
|
||||
case RuleEngine::RuleErrorTriggerTypeNotFound:
|
||||
returns.insert("success", false);
|
||||
returns.insert("errorMessage", "Device does not have such a trigger type.");
|
||||
break;
|
||||
}
|
||||
return returns;
|
||||
}
|
||||
20
server/jsonrpc/ruleshandler.h
Normal file
20
server/jsonrpc/ruleshandler.h
Normal file
@ -0,0 +1,20 @@
|
||||
#ifndef RULESHANDLER_H
|
||||
#define RULESHANDLER_H
|
||||
|
||||
#include "jsonhandler.h"
|
||||
|
||||
class RulesHandler : public JsonHandler
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit RulesHandler(QObject *parent = 0);
|
||||
|
||||
QString name() const override;
|
||||
|
||||
Q_INVOKABLE QVariantMap GetRules(const QVariantMap ¶ms);
|
||||
|
||||
Q_INVOKABLE QVariantMap AddRule(const QVariantMap ¶ms);
|
||||
|
||||
};
|
||||
|
||||
#endif // RULESHANDLER_H
|
||||
@ -1,299 +0,0 @@
|
||||
#include "jsonrpcserver.h"
|
||||
|
||||
#include "tcpserver.h"
|
||||
|
||||
#include "hivecore.h"
|
||||
#include "devicemanager.h"
|
||||
#include "deviceplugin.h"
|
||||
#include "deviceclass.h"
|
||||
#include "device.h"
|
||||
#include "rule.h"
|
||||
#include "ruleengine.h"
|
||||
|
||||
#include <QJsonDocument>
|
||||
#include <QStringList>
|
||||
|
||||
JsonRPCServer::JsonRPCServer(QObject *parent):
|
||||
QObject(parent),
|
||||
m_tcpServer(new TcpServer(this))
|
||||
{
|
||||
connect(m_tcpServer, &TcpServer::jsonDataAvailable, this, &JsonRPCServer::processData);
|
||||
m_tcpServer->startServer();
|
||||
}
|
||||
|
||||
void JsonRPCServer::processData(int clientId, const QByteArray &jsonData)
|
||||
{
|
||||
QJsonParseError error;
|
||||
QJsonDocument jsonDoc = QJsonDocument::fromJson(jsonData, &error);
|
||||
|
||||
if(error.error != QJsonParseError::NoError) {
|
||||
qDebug() << "failed to parse data" << jsonData << ":" << error.errorString();
|
||||
}
|
||||
qDebug() << "-------------------------\n" << jsonDoc.toJson();
|
||||
|
||||
QVariantMap message = jsonDoc.toVariant().toMap();
|
||||
|
||||
bool success;
|
||||
int commandId = message.value("id").toInt(&success);
|
||||
if (!success) {
|
||||
qWarning() << "Error parsing command. Missing \"id\":" << jsonData;
|
||||
return;
|
||||
}
|
||||
|
||||
QStringList commandList = message.value("method").toString().split('.');
|
||||
if (commandList.count() != 2) {
|
||||
qWarning() << "Error parsing method.\nGot:" << message.value("method").toString() << "\nExpected: \"Namespace.method\"";
|
||||
return;
|
||||
}
|
||||
|
||||
QString targetNamespace = commandList.first();
|
||||
QString method = commandList.last();
|
||||
QVariantMap params = message.value("params").toMap();
|
||||
|
||||
qDebug() << "got:" << targetNamespace << method << params;
|
||||
emit commandReceived(targetNamespace, method, params);
|
||||
|
||||
if (targetNamespace == "Devices") {
|
||||
handleDevicesMessage(clientId, commandId, method, params);
|
||||
} else if (targetNamespace == "Rules") {
|
||||
handleRulesMessage(clientId, commandId, method, params);
|
||||
} else if (targetNamespace == "Actions") {
|
||||
handleActionMessage(clientId, commandId, method, params);
|
||||
} else {
|
||||
qDebug() << "got unknown namespace" << targetNamespace;
|
||||
}
|
||||
}
|
||||
|
||||
void JsonRPCServer::handleDevicesMessage(int clientId, int commandId, const QString &method, const QVariantMap ¶ms)
|
||||
{
|
||||
if (method == "GetSupportedDevices") {
|
||||
QVariantMap params;
|
||||
QVariantList supportedDeviceList;
|
||||
foreach (const DeviceClass &deviceClass, HiveCore::instance()->deviceManager()->supportedDevices()) {
|
||||
supportedDeviceList.append(packDeviceClass(deviceClass));
|
||||
}
|
||||
params.insert("deviceClasses", supportedDeviceList);
|
||||
sendResponse(clientId, commandId, params);
|
||||
} else if (method == "GetPlugins") {
|
||||
QVariantMap params;
|
||||
QVariantList plugins;
|
||||
foreach (DevicePlugin *plugin, HiveCore::instance()->deviceManager()->plugins()) {
|
||||
QVariantMap pluginMap;
|
||||
pluginMap.insert("id", plugin->pluginId());
|
||||
pluginMap.insert("name", plugin->pluginName());
|
||||
pluginMap.insert("config", plugin->configuration());
|
||||
plugins.append(pluginMap);
|
||||
}
|
||||
params.insert("plugins", plugins);
|
||||
sendResponse(clientId, commandId, params);
|
||||
} else if (method == "SetPluginConfig") {
|
||||
QUuid pluginId = params.value("pluginId").toUuid();
|
||||
QVariantMap pluginParams = params.value("params").toMap();
|
||||
HiveCore::instance()->deviceManager()->plugin(pluginId)->setConfiguration(pluginParams);
|
||||
sendResponse(clientId, commandId);
|
||||
} else if (method == "AddConfiguredDevice") {
|
||||
QUuid deviceClass = params.value("deviceClass").toUuid();
|
||||
QVariantMap deviceParams = params.value("params").toMap();
|
||||
DeviceManager::DeviceError status = HiveCore::instance()->deviceManager()->addConfiguredDevice(deviceClass, deviceParams);
|
||||
switch(status) {
|
||||
case DeviceManager::DeviceErrorNoError:
|
||||
sendResponse(clientId, commandId);
|
||||
break;
|
||||
case DeviceManager::DeviceErrorDeviceClassNotFound:
|
||||
sendErrorResponse(clientId, commandId, "Error creating device. Device class not found.");
|
||||
break;
|
||||
case DeviceManager::DeviceErrorMissingParameter:
|
||||
sendErrorResponse(clientId, commandId, "Error creating device. Missing parameter.");
|
||||
break;
|
||||
case DeviceManager::DeviceErrorSetupFailed:
|
||||
sendErrorResponse(clientId, commandId, "Error creating device. Device setup failed.");
|
||||
break;
|
||||
default:
|
||||
sendErrorResponse(clientId, commandId, "Unknown error.");
|
||||
}
|
||||
} else if (method == "GetConfiguredDevices") {
|
||||
QVariantMap rspParams;
|
||||
QVariantList configuredDeviceList;
|
||||
foreach (Device *device, HiveCore::instance()->deviceManager()->configuredDevices()) {
|
||||
configuredDeviceList.append(packDevice(device));
|
||||
}
|
||||
rspParams.insert("devices", configuredDeviceList);
|
||||
sendResponse(clientId, commandId, rspParams);
|
||||
} else {
|
||||
sendErrorResponse(clientId, commandId, "No such method");
|
||||
}
|
||||
}
|
||||
|
||||
void JsonRPCServer::handleRulesMessage(int clientId, int commandId, const QString &method, const QVariantMap ¶ms)
|
||||
{
|
||||
if (method == "GetRules") {
|
||||
QVariantList rulesList;
|
||||
foreach (const Rule &rule, HiveCore::instance()->ruleEngine()->rules()) {
|
||||
QVariantMap ruleMap;
|
||||
ruleMap.insert("id", rule.id());
|
||||
ruleMap.insert("trigger", packTrigger(rule.trigger()));
|
||||
QVariantList actionList;
|
||||
foreach (const Action &action, rule.actions()) {
|
||||
actionList.append(packAction(action));
|
||||
}
|
||||
|
||||
ruleMap.insert("actions", actionList);
|
||||
rulesList.append(ruleMap);
|
||||
}
|
||||
QVariantMap rspParams;
|
||||
rspParams.insert("rules", rulesList);
|
||||
sendResponse(clientId, commandId, rspParams);
|
||||
} else if (method == "AddRule") {
|
||||
QVariantMap triggerMap = params.value("trigger").toMap();
|
||||
|
||||
QUuid triggerTypeId = triggerMap.value("triggerTypeId").toUuid();
|
||||
QUuid triggerDeviceId = triggerMap.value("deviceId").toUuid();
|
||||
QVariantMap triggerParams = triggerMap.value("params").toMap();
|
||||
Trigger trigger(triggerTypeId, triggerDeviceId, triggerParams);
|
||||
|
||||
QList<Action> actions;
|
||||
QVariantList actionList = params.value("actions").toList();
|
||||
foreach (const QVariant &actionVariant, actionList) {
|
||||
QVariantMap actionMap = actionVariant.toMap();
|
||||
Action action(actionMap.value("deviceId").toString());
|
||||
action.setName(actionMap.value("name").toString());
|
||||
action.setParams(actionMap.value("params").toMap());
|
||||
actions.append(action);
|
||||
}
|
||||
if (actions.count() == 0) {
|
||||
sendErrorResponse(clientId, commandId, "Missing parameter: \"actions\".");
|
||||
return;
|
||||
}
|
||||
|
||||
switch(HiveCore::instance()->ruleEngine()->addRule(trigger, actions)) {
|
||||
case RuleEngine::RuleErrorNoError:
|
||||
sendResponse(clientId, commandId);
|
||||
break;
|
||||
case RuleEngine::RuleErrorDeviceNotFound:
|
||||
sendErrorResponse(clientId, commandId, "No such device.");
|
||||
break;
|
||||
case RuleEngine::RuleErrorTriggerTypeNotFound:
|
||||
sendErrorResponse(clientId, commandId, "Device does not have such a trigger type.");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void JsonRPCServer::handleActionMessage(int clientId, int commandId, const QString &method, const QVariantMap ¶ms)
|
||||
{
|
||||
if (method == "ExecuteAction") {
|
||||
QVariantMap actionMap = params.value("action").toMap();
|
||||
QUuid deviceId = actionMap.value("deviceId").toUuid();
|
||||
QVariantMap actionParams = actionMap.value("params").toMap();
|
||||
|
||||
Action action(deviceId);
|
||||
action.setParams(actionParams);
|
||||
|
||||
qDebug() << "actions params in json" << action.params();
|
||||
|
||||
|
||||
DeviceManager::DeviceError error = HiveCore::instance()->deviceManager()->executeAction(action);
|
||||
switch (error) {
|
||||
case DeviceManager::DeviceErrorNoError:
|
||||
sendResponse(clientId, commandId);
|
||||
break;
|
||||
case DeviceManager::DeviceErrorDeviceNotFound:
|
||||
sendErrorResponse(clientId, commandId, "No such device");
|
||||
break;
|
||||
default:
|
||||
sendErrorResponse(clientId, commandId, "Unknown error.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QVariantMap JsonRPCServer::packDeviceClass(const DeviceClass &deviceClass)
|
||||
{
|
||||
QVariantMap variant;
|
||||
variant.insert("name", deviceClass.name());
|
||||
variant.insert("id", deviceClass.id());
|
||||
QVariantList stateTypes;
|
||||
foreach (const StateType &stateType, deviceClass.states()) {
|
||||
QVariantMap stateMap;
|
||||
stateMap.insert("id", stateType.id().toString());
|
||||
stateMap.insert("name", stateType.name());
|
||||
stateMap.insert("type", QVariant::typeToName(stateType.type()));
|
||||
|
||||
stateTypes.append(stateMap);
|
||||
}
|
||||
QVariantList triggerTypes;
|
||||
foreach (const TriggerType &triggerType, deviceClass.triggers()) {
|
||||
QVariantMap triggerMap;
|
||||
triggerMap.insert("id", triggerType.id().toString());
|
||||
triggerMap.insert("name", triggerType.name());
|
||||
triggerMap.insert("params", triggerType.parameters());
|
||||
|
||||
triggerTypes.append(triggerMap);
|
||||
}
|
||||
QVariantList actionTypes;
|
||||
foreach (const ActionType &actionType, deviceClass.actions()) {
|
||||
QVariantMap actionMap;
|
||||
actionMap.insert("id", actionType.id().toString());
|
||||
actionMap.insert("name", actionType.name());
|
||||
actionMap.insert("params", actionType.parameters());
|
||||
|
||||
actionTypes.append(actionMap);
|
||||
}
|
||||
variant.insert("params", deviceClass.params());
|
||||
variant.insert("states", stateTypes);
|
||||
variant.insert("triggers", triggerTypes);
|
||||
variant.insert("actions", actionTypes);
|
||||
return variant;
|
||||
}
|
||||
|
||||
QVariantMap JsonRPCServer::packDevice(Device *device)
|
||||
{
|
||||
QVariantMap variant;
|
||||
variant.insert("id", device->id());
|
||||
variant.insert("deviceClassId", device->deviceClassId());
|
||||
variant.insert("name", device->name());
|
||||
variant.insert("params", device->params());
|
||||
return variant;
|
||||
}
|
||||
|
||||
QVariantMap JsonRPCServer::packTrigger(const Trigger &trigger)
|
||||
{
|
||||
QVariantMap variant;
|
||||
variant.insert("id", trigger.triggerTypeId());
|
||||
variant.insert("deviceId", trigger.deviceId());
|
||||
variant.insert("params", trigger.params());
|
||||
return variant;
|
||||
}
|
||||
|
||||
QVariantMap JsonRPCServer::packAction(const Action &action)
|
||||
{
|
||||
QVariantMap variant;
|
||||
variant.insert("id", action.id());
|
||||
variant.insert("deviceId", action.deviceId());
|
||||
variant.insert("name", action.name());
|
||||
variant.insert("params", action.params());
|
||||
return variant;
|
||||
}
|
||||
|
||||
void JsonRPCServer::sendResponse(int clientId, int commandId, const QVariantMap ¶ms)
|
||||
{
|
||||
QVariantMap rsp;
|
||||
rsp.insert("id", commandId);
|
||||
rsp.insert("status", "success");
|
||||
rsp.insert("params", params);
|
||||
|
||||
QJsonDocument jsonDoc = QJsonDocument::fromVariant(rsp);
|
||||
m_tcpServer->sendResponse(clientId, jsonDoc.toJson());
|
||||
}
|
||||
|
||||
void JsonRPCServer::sendErrorResponse(int clientId, int commandId, const QString &error)
|
||||
{
|
||||
QVariantMap rsp;
|
||||
rsp.insert("id", commandId);
|
||||
rsp.insert("status", "error");
|
||||
rsp.insert("error", error);
|
||||
|
||||
QJsonDocument jsonDoc = QJsonDocument::fromVariant(rsp);
|
||||
m_tcpServer->sendResponse(clientId, jsonDoc.toJson());
|
||||
}
|
||||
|
||||
|
||||
@ -40,7 +40,6 @@ RuleEngine::RuleEngine(QObject *parent) :
|
||||
foreach (const QString &actionIdString, settings.childGroups()) {
|
||||
settings.beginGroup(actionIdString);
|
||||
Action action = Action(settings.value("deviceId").toUuid(), settings.value("id").toUuid());
|
||||
action.setName(settings.value("name").toString());
|
||||
action.setParams(settings.value("params").toMap());
|
||||
settings.endGroup();
|
||||
actions.append(action);
|
||||
@ -136,9 +135,8 @@ RuleEngine::RuleError RuleEngine::addRule(const Trigger &trigger, const QList<St
|
||||
|
||||
settings.beginGroup("actions");
|
||||
foreach (const Action &action, rule.actions()) {
|
||||
settings.beginGroup(action.id().toString());
|
||||
settings.beginGroup(action.actionTypeId().toString());
|
||||
settings.setValue("deviceId", action.deviceId());
|
||||
settings.setValue("name", action.name());
|
||||
settings.setValue("params", action.params());
|
||||
settings.endGroup();
|
||||
}
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
TARGET = hive
|
||||
TEMPLATE = app
|
||||
|
||||
INCLUDEPATH += ../libhive
|
||||
INCLUDEPATH += ../libhive jsonrpc
|
||||
|
||||
target.path = /usr/bin
|
||||
INSTALLS += target
|
||||
@ -12,17 +12,27 @@ CONFIG += c++11
|
||||
LIBS += -L../libhive/ -lhive
|
||||
|
||||
SOURCES += main.cpp \
|
||||
hivecore.cpp \
|
||||
jsonrpcserver.cpp \
|
||||
tcpserver.cpp \
|
||||
ruleengine.cpp \
|
||||
rule.cpp
|
||||
hivecore.cpp \
|
||||
tcpserver.cpp \
|
||||
ruleengine.cpp \
|
||||
rule.cpp \
|
||||
jsonrpc/jsonrpcserver.cpp \
|
||||
jsonrpc/jsonhandler.cpp \
|
||||
jsonrpc/devicehandler.cpp \
|
||||
jsonrpc/jsontypes.cpp \
|
||||
jsonrpc/ruleshandler.cpp \
|
||||
jsonrpc/actionhandler.cpp
|
||||
|
||||
HEADERS += hivecore.h \
|
||||
jsonrpcserver.h \
|
||||
tcpserver.h \
|
||||
ruleengine.h \
|
||||
rule.h
|
||||
tcpserver.h \
|
||||
ruleengine.h \
|
||||
rule.h \
|
||||
jsonrpc/jsonrpcserver.h \
|
||||
jsonrpc/jsonhandler.h \
|
||||
jsonrpc/devicehandler.h \
|
||||
jsonrpc/jsontypes.h \
|
||||
jsonrpc/ruleshandler.h \
|
||||
jsonrpc/actionhandler.h
|
||||
|
||||
# FIXME: Drop this and link them dynamically
|
||||
LIBS += -L../plugins/deviceplugins/elro/ -lhive_devicepluginelro
|
||||
|
||||
@ -10,18 +10,18 @@ elif [ -z $2 ]; then
|
||||
else
|
||||
if [ $2 == "elroremote" ]; then
|
||||
# Adds an ELRO remote control on channel 00000
|
||||
(echo '{"id":1, "method":"Devices.AddConfiguredDevice", "params":{"deviceClass": "{d85c1ef4-197c-4053-8e40-707aa671d302}","params":{"channel1":"true", "channel2":"false", "channel3":"false", "channel4": "false", "channel5":"false" }}}'; sleep 1) | nc $1 1234
|
||||
(echo '{"id":1, "method":"Devices.AddConfiguredDevice", "params":{"deviceClassId": "{d85c1ef4-197c-4053-8e40-707aa671d302}","deviceParams":{"channel1":"true", "channel2":"false", "channel3":"false", "channel4": "false", "channel5":"false" }}}'; sleep 1) | nc $1 1234
|
||||
elif [ $2 == "elroswitch" ]; then
|
||||
# Adds a ELRO power switch on channel 00000 and group E
|
||||
(echo '{"id":1, "method":"Devices.AddConfiguredDevice", "params":{"deviceClass": "{308ae6e6-38b3-4b3a-a513-3199da2764f8}","params":{"channel1":"false","channel2":"false", "channel3":"false", "channel4": "false","channel5":"false","A":"false","B":"true","C":"false","D":"false","E":"false" }}}'; sleep 1) | nc $1 1234
|
||||
(echo '{"id":1, "method":"Devices.AddConfiguredDevice", "params":{"deviceClassId": "{308ae6e6-38b3-4b3a-a513-3199da2764f8}","deviceParams":{"channel1":"false","channel2":"false", "channel3":"false", "channel4": "false","channel5":"false","A":"false","B":"true","C":"false","D":"false","E":"false" }}}'; sleep 1) | nc $1 1234
|
||||
elif [ $2 == "intertechnoremote" ]; then
|
||||
# Adds an intertechno remote control
|
||||
(echo '{"id":1, "method":"Devices.AddConfiguredDevice", "params":{"deviceClass": "{ab73ad2f-6594-45a3-9063-8f72d365c5e5}","params":{"familyCode":"J"}}}'; sleep 1) | nc $1 1234
|
||||
(echo '{"id":1, "method":"Devices.AddConfiguredDevice", "params":{"deviceClassId": "{ab73ad2f-6594-45a3-9063-8f72d365c5e5}","deviceParams":{"familyCode":"J"}}}'; sleep 1) | nc $1 1234
|
||||
elif [ $2 == "meisteranker" ]; then
|
||||
# Adds an intertechno remote control
|
||||
(echo '{"id":1, "method":"Devices.AddConfiguredDevice", "params":{"deviceClass": "{e37e9f34-95b9-4a22-ae4f-e8b874eec871}","params":{"id":"1"}}}'; sleep 1) | nc $1 1234
|
||||
(echo '{"id":1, "method":"Devices.AddConfiguredDevice", "params":{"deviceClassId": "{e37e9f34-95b9-4a22-ae4f-e8b874eec871}","deviceParams":{"id":"1"}}}'; sleep 1) | nc $1 1234
|
||||
elif [ $2 == "wifidetector" ]; then
|
||||
# Adds a WiFi detector
|
||||
(echo '{"id":1, "method":"Devices.AddConfiguredDevice", "params":{"deviceClass": "{bd216356-f1ec-4324-9785-6982d2174e17}","params":{"mac":"90:cf:15:1b:ce:bb"}}}'; sleep 1) | nc $1 1234
|
||||
(echo '{"id":1, "method":"Devices.AddConfiguredDevice", "params":{"deviceClassId": "{bd216356-f1ec-4324-9785-6982d2174e17}","deviceParams":{"mac":"90:cf:15:1b:ce:bb"}}}'; sleep 1) | nc $1 1234
|
||||
fi
|
||||
fi
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
#!/bin/bash
|
||||
|
||||
if test -z $3; then
|
||||
echo "usage: $1 host triggerTypeId sourceDeviceId targetDeviceId"
|
||||
if test -z $5; then
|
||||
echo "usage: $0 host sourceDevice triggerTypeId targetDeviceId actionTypeId"
|
||||
else
|
||||
(echo '{"id":1, "method":"Rules.AddRule", "params":{"trigger": {"triggerTypeId": "'$2'", "deviceId":"'$3'", "params":{"power":"true"}}, "actions": [ { "deviceId":"'$4'", "name":"rule 1", "params":{"power":"true"}}, { "deviceId":"'$5'", "name":"rule 1", "params":{"power":"true"}}]}}'; sleep 1) | nc $1 1234
|
||||
(echo '{"id":1, "method":"Rules.AddRule", "params":{"trigger": {"triggerTypeId": "'$2'", "deviceId":"'$3'", "params":{"power":"false"}}, "actions": [ { "deviceId":"'$4'", "name":"rule 1", "params":{"power":"false"}},{ "deviceId":"'$5'", "name":"rule 1", "params":{"power":"true"}}]}}'; sleep 1) | nc $1 1234
|
||||
(echo '{"id":1, "method":"Rules.AddRule", "params":{"trigger": {"triggerTypeId": "'$3'", "deviceId":"'$2'", "params":{"power":"true"}}, "actions": [ { "deviceId":"'$4'", "actionTypeId":"'$5'", "params":{"power":"true"}}]}}'; sleep 1) | nc $1 1234
|
||||
# (echo '{"id":1, "method":"Rules.AddRule", "params":{"trigger": {"triggerTypeId": "'$2'", "deviceId":"'$3'", "params":{"power":"false"}}, "actions": [ { "deviceId":"'$4'", "name":"rule 1", "params":{"power":"false"}},{ "deviceId":"'$5'", "name":"rule 1", "params":{"power":"true"}}]}}'; sleep 1) | nc $1 1234
|
||||
fi
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
#!/bin/bash
|
||||
|
||||
if [ -z $1 ]; then
|
||||
echo "usage: $0 host deviceId power"
|
||||
if [ -z $4 ]; then
|
||||
echo "usage: $0 host actionTypeId deviceId power"
|
||||
else
|
||||
(echo '{"id":1, "method":"Actions.ExecuteAction","params":{"action":{"deviceId":"{'$2'}","params":{"power":"'$3'"}}}}'; sleep 1) | nc $1 1234
|
||||
(echo '{"id":1, "method":"Actions.ExecuteAction","params":{"actionTypeId": "{'$2'}", "deviceId":"{'$3'}","params":{"power":"'$4'"}}}'; sleep 1) | nc $1 1234
|
||||
fi
|
||||
|
||||
7
tests/getactiontypes.sh
Executable file
7
tests/getactiontypes.sh
Executable file
@ -0,0 +1,7 @@
|
||||
#!/bin/bash
|
||||
|
||||
if [ -z $2 ]; then
|
||||
echo "usage: $0 host deviceClassId"
|
||||
else
|
||||
(echo '{"id":1, "method":"Devices.GetActionTypes", "params":{"deviceClassId":"'$2'"}}'; sleep 1) | nc $1 1234
|
||||
fi
|
||||
7
tests/gettriggertypes.sh
Executable file
7
tests/gettriggertypes.sh
Executable file
@ -0,0 +1,7 @@
|
||||
#!/bin/bash
|
||||
|
||||
if [ -z $2 ]; then
|
||||
echo "usage: $0 host deviceClassId"
|
||||
else
|
||||
(echo '{"id":1, "method":"Devices.GetTriggerTypes", "params":{"deviceClassId":"'$2'"}}'; sleep 1) | nc $1 1234
|
||||
fi
|
||||
7
tests/introspect.sh
Executable file
7
tests/introspect.sh
Executable file
@ -0,0 +1,7 @@
|
||||
#!/bin/bash
|
||||
|
||||
if [ -z $1 ]; then
|
||||
echo "usage: $0 host"
|
||||
else
|
||||
(echo '{"id":1, "method": "JSONRPC.Introspect"}'; sleep 1) | nc $1 1234
|
||||
fi
|
||||
Reference in New Issue
Block a user