Allow registering QMetaObjects on JSON api

pull/228/head
Michael Zanetti 2019-10-25 13:13:06 +02:00
parent e2cf9cb5c3
commit bdd9876a88
64 changed files with 762 additions and 519 deletions

View File

@ -865,6 +865,43 @@ QString DeviceManagerImplementation::translate(const PluginId &pluginId, const Q
return m_translator->translate(pluginId, string, locale);
}
ParamType DeviceManagerImplementation::translateParamType(const PluginId &pluginId, const ParamType &paramType, const QLocale &locale)
{
ParamType translatedParamType = paramType;
translatedParamType.setDisplayName(translate(pluginId, paramType.displayName(), locale));
return translatedParamType;
}
DeviceClass DeviceManagerImplementation::translateDeviceClass(const DeviceClass &deviceClass, const QLocale &locale)
{
DeviceClass translatedDeviceClass = deviceClass;
translatedDeviceClass.setDisplayName(translate(deviceClass.pluginId(), deviceClass.displayName(), locale));
ParamTypes translatedSettingsTypes;
foreach (const ParamType &paramType, deviceClass.settingsTypes()) {
translatedSettingsTypes.append(translateParamType(deviceClass.pluginId(), paramType, locale));
}
translatedDeviceClass.setSettingsTypes(translatedSettingsTypes);
return translatedDeviceClass;
}
Vendor DeviceManagerImplementation::translateVendor(const Vendor &vendor, const QLocale &locale)
{
DevicePlugin *plugin = nullptr;
foreach (DevicePlugin *p, m_devicePlugins) {
if (p->supportedVendors().contains(vendor)) {
plugin = p;
}
}
if (!plugin) {
return vendor;
}
Vendor translatedVendor = vendor;
translatedVendor.setDisplayName(translate(plugin->pluginId(), vendor.displayName(), locale));
return translatedVendor;
}
/*! Returns the \l{Device} with the given \a id. Null if the id couldn't be found. */
Device *DeviceManagerImplementation::findConfiguredDevice(const DeviceId &id) const
{

View File

@ -107,6 +107,9 @@ public:
BrowserItemActionInfo *executeBrowserItemAction(const BrowserItemAction &browserItemAction) override;
QString translate(const PluginId &pluginId, const QString &string, const QLocale &locale) override;
ParamType translateParamType(const PluginId &pluginId, const ParamType &paramType, const QLocale &locale) override;
DeviceClass translateDeviceClass(const DeviceClass &deviceClass, const QLocale &locale) override;
Vendor translateVendor(const Vendor &vendor, const QLocale &locale) override;
signals:
void loaded();

View File

@ -41,6 +41,7 @@
#include "devices/browseractioninfo.h"
#include "devices/browseritemactioninfo.h"
#include "types/action.h"
#include "types/actiontype.h"
#include "loggingcategories.h"
namespace nymeaserver {
@ -49,12 +50,15 @@ namespace nymeaserver {
ActionHandler::ActionHandler(QObject *parent) :
JsonHandler(parent)
{
// Enums
registerEnum<Types::InputType>();
registerEnum<Types::Unit>();
// Objects
QVariantMap action;
action.insert("actionTypeId", enumValueName(Uuid));
action.insert("deviceId", enumValueName(Uuid));
action.insert("o:params", QVariantList() << objectRef("Param"));
registerObject("Action", action);
registerObject<ParamType, ParamTypes>();
registerObject<Param, ParamList>();
registerObject<ActionType>();
registerObject<Action>();
// Methods
QString description; QVariantMap params; QVariantMap returns;
@ -125,14 +129,18 @@ JsonReply* ActionHandler::ExecuteAction(const QVariantMap &params)
JsonReply *ActionHandler::GetActionType(const QVariantMap &params) const
{
QLocale locale = params.value("locale").toLocale();
qCDebug(dcJsonRpc) << "asked for action type" << params;
ActionTypeId actionTypeId(params.value("actionTypeId").toString());
foreach (const DeviceClass &deviceClass, NymeaCore::instance()->deviceManager()->supportedDevices()) {
foreach (const ActionType &actionType, deviceClass.actionTypes()) {
if (actionType.id() == actionTypeId) {
ActionType translatedActionType = actionType;
translatedActionType.setDisplayName(NymeaCore::instance()->deviceManager()->translate(deviceClass.pluginId(), actionType.displayName(), locale));
QVariantMap data;
data.insert("deviceError", enumValueName<Device::DeviceError>(Device::DeviceErrorNoError));
data.insert("actionType", DeviceHandler::packActionType(actionType, deviceClass.pluginId(), params.value("locale").toLocale()));
data.insert("actionType", pack(translatedActionType));
return createReply(data);
}
}

View File

@ -72,25 +72,9 @@ ConfigurationHandler::ConfigurationHandler(QObject *parent):
registerEnum<NymeaConfiguration::ConfigurationError>();
// Objects
QVariantMap serverConfiguration;
serverConfiguration.insert("id", enumValueName(String));
serverConfiguration.insert("address", enumValueName(String));
serverConfiguration.insert("port", enumValueName(Uint));
serverConfiguration.insert("sslEnabled", enumValueName(Bool));
serverConfiguration.insert("authenticationEnabled", enumValueName(Bool));
registerObject("ServerConfiguration", serverConfiguration);
QVariantMap webServerConfiguration = serverConfiguration;
webServerConfiguration.insert("publicFolder", enumValueName(String));
registerObject("WebServerConfiguration", webServerConfiguration);
QVariantMap mqttPolicy;
mqttPolicy.insert("clientId", enumValueName(String));
mqttPolicy.insert("username", enumValueName(String));
mqttPolicy.insert("password", enumValueName(String));
mqttPolicy.insert("allowedPublishTopicFilters", enumValueName(StringList));
mqttPolicy.insert("allowedSubscribeTopicFilters", enumValueName(StringList));
registerObject("MqttPolicy", mqttPolicy);
registerObject<ServerConfiguration>();
registerObject<WebServerConfiguration>();
registerObject<MqttPolicy>();
// Methods
QString description; QVariantMap params; QVariantMap returns;
@ -327,20 +311,20 @@ JsonReply *ConfigurationHandler::GetConfigurations(const QVariantMap &params) co
returns.insert("basicConfiguration", packBasicConfiguration());
QVariantList tcpServerConfigs;
foreach (const ServerConfiguration &config, NymeaCore::instance()->configuration()->tcpServerConfigurations()) {
tcpServerConfigs.append(packServerConfiguration(config));
tcpServerConfigs.append(pack(config));
}
returns.insert("tcpServerConfigurations", tcpServerConfigs);
QVariantList webServerConfigs;
foreach (const WebServerConfiguration &config, NymeaCore::instance()->configuration()->webServerConfigurations()) {
webServerConfigs.append(packWebServerConfiguration(config));
webServerConfigs.append(pack(config));
}
returns.insert("webServerConfigurations", webServerConfigs);
QVariantList webSocketServerConfigs;
foreach (const ServerConfiguration &config, NymeaCore::instance()->configuration()->webSocketServerConfigurations()) {
webSocketServerConfigs.append(packServerConfiguration(config));
webSocketServerConfigs.append(pack(config));
}
returns.insert("webSocketServerConfigurations", webSocketServerConfigs);
@ -503,7 +487,7 @@ JsonReply *ConfigurationHandler::GetMqttServerConfigurations(const QVariantMap &
QVariantMap ret;
QVariantList mqttServerConfigs;
foreach (const ServerConfiguration &config, NymeaCore::instance()->configuration()->mqttServerConfigurations()) {
mqttServerConfigs << packServerConfiguration(config);
mqttServerConfigs << pack(config);
}
ret.insert("mqttServerConfigurations", mqttServerConfigs);
return createReply(ret);
@ -545,7 +529,7 @@ JsonReply *ConfigurationHandler::GetMqttPolicies(const QVariantMap &params) cons
Q_UNUSED(params)
QVariantList mqttPolicies;
foreach (const MqttPolicy &policy, NymeaCore::instance()->configuration()->mqttPolicies()) {
mqttPolicies << packMqttPolicy(policy);
mqttPolicies << pack(policy);
}
QVariantMap ret;
ret.insert("mqttPolicies", mqttPolicies);
@ -592,7 +576,7 @@ void ConfigurationHandler::onTcpServerConfigurationChanged(const QString &id)
{
qCDebug(dcJsonRpc()) << "Notification: TCP server configuration changed";
QVariantMap params;
params.insert("tcpServerConfiguration", packServerConfiguration(NymeaCore::instance()->configuration()->tcpServerConfigurations().value(id)));
params.insert("tcpServerConfiguration", pack(NymeaCore::instance()->configuration()->tcpServerConfigurations().value(id)));
emit TcpServerConfigurationChanged(params);
}
@ -608,7 +592,7 @@ void ConfigurationHandler::onWebServerConfigurationChanged(const QString &id)
{
qCDebug(dcJsonRpc()) << "Notification: web server configuration changed";
QVariantMap params;
params.insert("webServerConfiguration", packWebServerConfiguration(NymeaCore::instance()->configuration()->webServerConfigurations().value(id)));
params.insert("webServerConfiguration", pack(NymeaCore::instance()->configuration()->webServerConfigurations().value(id)));
emit WebServerConfigurationChanged(params);
}
@ -624,7 +608,7 @@ void ConfigurationHandler::onWebSocketServerConfigurationChanged(const QString &
{
qCDebug(dcJsonRpc()) << "Notification: web socket server configuration changed";
QVariantMap params;
params.insert("webSocketServerConfiguration", packServerConfiguration(NymeaCore::instance()->configuration()->webSocketServerConfigurations().value(id)));
params.insert("webSocketServerConfiguration", pack(NymeaCore::instance()->configuration()->webSocketServerConfigurations().value(id)));
emit WebSocketServerConfigurationChanged(params);
}
@ -640,7 +624,7 @@ void ConfigurationHandler::onMqttServerConfigurationChanged(const QString &id)
{
qCDebug(dcJsonRpc()) << "Notification: MQTT server configuration changed";
QVariantMap params;
params.insert("mqttServerConfiguration", packServerConfiguration(NymeaCore::instance()->configuration()->mqttServerConfigurations().value(id)));
params.insert("mqttServerConfiguration", pack(NymeaCore::instance()->configuration()->mqttServerConfigurations().value(id)));
emit MqttServerConfigurationChanged(params);
}
@ -656,7 +640,7 @@ void ConfigurationHandler::onMqttPolicyChanged(const QString &clientId)
{
qCDebug(dcJsonRpc()) << "Notification: MQTT policy changed";
QVariantMap params;
params.insert("policy", packMqttPolicy(NymeaCore::instance()->configuration()->mqttPolicies().value(clientId)));
params.insert("policy", pack(NymeaCore::instance()->configuration()->mqttPolicies().value(clientId)));
emit MqttPolicyChanged(params);
}
@ -680,34 +664,6 @@ QVariantMap ConfigurationHandler::packBasicConfiguration()
return basicConfiguration;
}
QVariantMap ConfigurationHandler::packServerConfiguration(const ServerConfiguration &config)
{
QVariantMap serverConfiguration;
serverConfiguration.insert("id", config.id);
serverConfiguration.insert("address", config.address.toString());
serverConfiguration.insert("port", config.port);
serverConfiguration.insert("sslEnabled", config.sslEnabled);
serverConfiguration.insert("authenticationEnabled", config.authenticationEnabled);
return serverConfiguration;
}
QVariantMap ConfigurationHandler::packWebServerConfiguration(const WebServerConfiguration &config)
{
QVariantMap webServerConfiguration = packServerConfiguration(config);
webServerConfiguration.insert("publicFolder", config.publicFolder);
return webServerConfiguration;
}
QVariantMap ConfigurationHandler::packMqttPolicy(const MqttPolicy &policy)
{
QVariantMap policyMap;
policyMap.insert("clientId", policy.clientId);
policyMap.insert("username", policy.username);
policyMap.insert("password", policy.password);
policyMap.insert("allowedPublishTopicFilters", policy.allowedPublishTopicFilters);
policyMap.insert("allowedSubscribeTopicFilters", policy.allowedSubscribeTopicFilters);
return policyMap;
}
MqttPolicy ConfigurationHandler::unpackMqttPolicy(const QVariantMap &mqttPolicyMap)
{
@ -741,6 +697,7 @@ WebServerConfiguration ConfigurationHandler::unpackWebServerConfiguration(const
webServerConfiguration.sslEnabled = tmp.sslEnabled;
webServerConfiguration.authenticationEnabled = tmp.authenticationEnabled;
webServerConfiguration.publicFolder = webServerConfigurationMap.value("publicFolder").toString();
qWarning() << "Unpacking web server config:" << webServerConfigurationMap;
return webServerConfiguration;
}

View File

@ -92,9 +92,6 @@ private slots:
private:
static QVariantMap packBasicConfiguration();
static QVariantMap packServerConfiguration(const ServerConfiguration &config);
static QVariantMap packWebServerConfiguration(const WebServerConfiguration &config);
static QVariantMap packMqttPolicy(const MqttPolicy &policy);
static ServerConfiguration unpackServerConfiguration(const QVariantMap &serverConfigurationMap);
static WebServerConfiguration unpackWebServerConfiguration(const QVariantMap &webServerConfigurationMap);

View File

@ -80,7 +80,7 @@ DeviceHandler::DeviceHandler(QObject *parent) :
// Enums
registerEnum<Device::DeviceError>();
registerEnum<DeviceClass::SetupMethod>();
registerEnum<DeviceClass::CreateMethod>();
registerEnum<DeviceClass::CreateMethod, DeviceClass::CreateMethods>();
registerEnum<Types::Unit>();
registerEnum<Types::InputType>();
registerEnum<RuleEngine::RemovePolicy>();
@ -88,109 +88,20 @@ DeviceHandler::DeviceHandler(QObject *parent) :
registerEnum<MediaBrowserItem::MediaBrowserIcon>();
// Objects
QVariantMap paramType;
paramType.insert("id", enumValueName(Uuid));
paramType.insert("name", enumValueName(String));
paramType.insert("displayName", enumValueName(String));
paramType.insert("type", enumRef<BasicType>());
paramType.insert("index", enumValueName(Int));
paramType.insert("o:defaultValue", enumValueName(Variant));
paramType.insert("o:minValue", enumValueName(Variant));
paramType.insert("o:maxValue", enumValueName(Variant));
paramType.insert("o:allowedValues", QVariantList() << enumValueName(Variant));
paramType.insert("o:inputType", enumRef<Types::InputType>());
paramType.insert("o:unit", enumRef<Types::Unit>());
paramType.insert("o:readOnly", enumValueName(Bool));
registerObject("ParamType", paramType);
QVariantMap param;
param.insert("paramTypeId", enumValueName(Uuid));
param.insert("value", enumValueName(Variant));
registerObject("Param", param);
QVariantMap plugin;
plugin.insert("id", enumValueName(Uuid));
plugin.insert("name", enumValueName(String));
plugin.insert("displayName", enumValueName(String));
plugin.insert("paramTypes", QVariantList() << objectRef("ParamType"));
registerObject("Plugin", plugin);
QVariantMap vendor;
vendor.insert("id", enumValueName(Uuid));
vendor.insert("name", enumValueName(String));
vendor.insert("displayName", enumValueName(String));
registerObject("Vendor", vendor);
QVariantMap eventType;
eventType.insert("id", enumValueName(Uuid));
eventType.insert("name", enumValueName(String));
eventType.insert("displayName", enumValueName(String));
eventType.insert("index", enumValueName(Int));
eventType.insert("paramTypes", QVariantList() << objectRef("ParamType"));
registerObject("EventType", eventType);
QVariantMap stateType;
stateType.insert("id", enumValueName(Uuid));
stateType.insert("name", enumValueName(String));
stateType.insert("displayName", enumValueName(String));
stateType.insert("type", enumRef<BasicType>());
stateType.insert("index", enumValueName(Int));
stateType.insert("defaultValue", enumValueName(Variant));
stateType.insert("o:unit", enumRef<Types::Unit>());
stateType.insert("o:minValue", enumValueName(Variant));
stateType.insert("o:maxValue", enumValueName(Variant));
stateType.insert("o:possibleValues", QVariantList() << enumValueName(Variant));
registerObject("StateType", stateType);
QVariantMap actionType;
actionType.insert("id", enumValueName(Uuid));
actionType.insert("name", enumValueName(String));
actionType.insert("displayName", enumValueName(String));
actionType.insert("index", enumValueName(Int));
actionType.insert("paramTypes", QVariantList() << objectRef("ParamType"));
registerObject("ActionType", actionType);
QVariantMap deviceClass;
deviceClass.insert("id", enumValueName(Uuid));
deviceClass.insert("vendorId", enumValueName(Uuid));
deviceClass.insert("pluginId", enumValueName(Uuid));
deviceClass.insert("name", enumValueName(String));
deviceClass.insert("displayName", enumValueName(String));
deviceClass.insert("interfaces", QVariantList() << enumValueName(String));
deviceClass.insert("browsable", enumValueName(Bool));
deviceClass.insert("setupMethod", enumRef<DeviceClass::SetupMethod>());
deviceClass.insert("createMethods", QVariantList() << enumRef<DeviceClass::CreateMethod>());
deviceClass.insert("stateTypes", QVariantList() << objectRef("StateType"));
deviceClass.insert("eventTypes", QVariantList() << objectRef("EventType"));
deviceClass.insert("actionTypes", QVariantList() << objectRef("ActionType"));
deviceClass.insert("browserItemActionTypes", QVariantList() << objectRef("ActionType"));
deviceClass.insert("paramTypes", QVariantList() << objectRef("ParamType"));
deviceClass.insert("settingsTypes", QVariantList() << objectRef("ParamType"));
deviceClass.insert("discoveryParamTypes", QVariantList() << objectRef("ParamType"));
registerObject("DeviceClass", deviceClass);
QVariantMap deviceDescriptor;
deviceDescriptor.insert("id", enumValueName(Uuid));
deviceDescriptor.insert("deviceId", enumValueName(Uuid));
deviceDescriptor.insert("title", enumValueName(String));
deviceDescriptor.insert("description", enumValueName(String));
deviceDescriptor.insert("deviceParams", QVariantList() << objectRef("Param"));
registerObject("DeviceDescriptor", deviceDescriptor);
QVariantMap device;
device.insert("id", enumValueName(Uuid));
device.insert("deviceClassId", enumValueName(Uuid));
device.insert("name", enumValueName(String));
device.insert("params", QVariantList() << objectRef("Param"));
device.insert("settings", QVariantList() << objectRef("Param"));
QVariantMap stateValues;
stateValues.insert("stateTypeId", enumValueName(Uuid));
stateValues.insert("value", enumValueName(Variant));
device.insert("states", QVariantList() << stateValues);
device.insert("setupComplete", enumValueName(Bool));
device.insert("o:parentId", enumValueName(Uuid));
registerObject("Device", device);
registerObject<ParamType, ParamTypes>();
registerObject<Param, ParamList>();
registerObject<DevicePlugin>();
registerObject<Vendor>();
registerObject<EventType, EventTypes>();
registerObject<StateType, StateTypes>();
registerObject<ActionType, ActionTypes>();
registerObject<DeviceClass>();
registerObject<DeviceDescriptor>();
registerObject<State, States>();
registerObject<Device>();
// Regsitering browseritem manually for now. Not sure how to deal with the
// polymorphism in int (e.g MediaBrowserItem)
QVariantMap browserItem;
browserItem.insert("id", enumValueName(String));
browserItem.insert("displayName", enumValueName(String));
@ -219,7 +130,7 @@ DeviceHandler::DeviceHandler(QObject *parent) :
params.clear(); returns.clear();
description = "Returns a list of loaded plugins.";
returns.insert("plugins", QVariantList() << objectRef("Plugin"));
returns.insert("plugins", QVariantList() << objectRef("DevicePlugin"));
registerMethod("GetPlugins", description, params, returns);
params.clear(); returns.clear();
@ -467,18 +378,8 @@ JsonReply* DeviceHandler::GetSupportedVendors(const QVariantMap &params) const
QVariantList vendors;
foreach (const Vendor &vendor, NymeaCore::instance()->deviceManager()->supportedVendors()) {
DevicePlugin *plugin = nullptr;
foreach (DevicePlugin *p, NymeaCore::instance()->deviceManager()->plugins()) {
if (p->supportedVendors().contains(vendor)) {
plugin = p;
}
}
QVariantMap variantMap;
variantMap.insert("id", vendor.id().toString());
variantMap.insert("name", vendor.name());
variantMap.insert("displayName", NymeaCore::instance()->deviceManager()->translate(plugin->pluginId(), vendor.displayName(), locale));
vendors.append(variantMap);
Vendor translatedVendor = NymeaCore::instance()->deviceManager()->translateVendor(vendor, locale);
vendors.append(pack(translatedVendor));
}
QVariantMap returns;
@ -492,8 +393,10 @@ JsonReply* DeviceHandler::GetSupportedDevices(const QVariantMap &params) const
VendorId vendorId = VendorId(params.value("vendorId").toString());
QVariantMap returns;
QVariantList deviceClasses;
foreach (const DeviceClass &deviceClass, NymeaCore::instance()->deviceManager()->supportedDevices(vendorId))
deviceClasses.append(packDeviceClass(deviceClass, locale));
foreach (const DeviceClass &deviceClass, NymeaCore::instance()->deviceManager()->supportedDevices(vendorId)) {
DeviceClass translatedDeviceClass = NymeaCore::instance()->deviceManager()->translateDeviceClass(deviceClass, locale);
deviceClasses.append(pack(translatedDeviceClass));
}
returns.insert("deviceClasses", deviceClasses);
return createReply(returns);
@ -511,14 +414,14 @@ JsonReply *DeviceHandler::GetDiscoveredDevices(const QVariantMap &params) const
JsonReply *reply = createAsyncReply("GetDiscoveredDevices");
DeviceDiscoveryInfo *info = NymeaCore::instance()->deviceManager()->discoverDevices(deviceClassId, discoveryParams);
connect(info, &DeviceDiscoveryInfo::finished, reply, [reply, info, locale](){
connect(info, &DeviceDiscoveryInfo::finished, reply, [this, reply, info, locale](){
QVariantMap returns;
returns.insert("deviceError", enumValueName<Device::DeviceError>(info->status()));
if (info->status() == Device::DeviceErrorNoError) {
QVariantList deviceDescriptorList;
foreach (const DeviceDescriptor &deviceDescriptor, info->deviceDescriptors()) {
deviceDescriptorList.append(packDeviceDescriptor(deviceDescriptor));
deviceDescriptorList.append(pack(deviceDescriptor));
}
returns.insert("deviceDescriptors", deviceDescriptorList);
}
@ -540,7 +443,9 @@ JsonReply* DeviceHandler::GetPlugins(const QVariantMap &params) const
QVariantList plugins;
foreach (DevicePlugin* plugin, NymeaCore::instance()->deviceManager()->plugins()) {
plugins.append(packPlugin(plugin, locale));
QVariantMap packedPlugin = pack(*plugin);
packedPlugin["displayName"] = NymeaCore::instance()->deviceManager()->translate(plugin->pluginId(), plugin->pluginDisplayName(), locale);
plugins.append(packedPlugin);
}
QVariantMap returns;
@ -560,7 +465,7 @@ JsonReply *DeviceHandler::GetPluginConfiguration(const QVariantMap &params) cons
QVariantList paramVariantList;
foreach (const Param &param, plugin->configuration()) {
paramVariantList.append(packParam(param));
paramVariantList.append(pack(param));
}
returns.insert("configuration", paramVariantList);
returns.insert("deviceError", enumValueName<Device::DeviceError>(Device::DeviceErrorNoError));
@ -820,12 +725,15 @@ JsonReply* DeviceHandler::GetActionTypes(const QVariantMap &params) const
JsonReply* DeviceHandler::GetStateTypes(const QVariantMap &params) const
{
QLocale locale = params.value("locale").toLocale();
QVariantMap returns;
QVariantList stateList;
DeviceClass deviceClass = NymeaCore::instance()->deviceManager()->findDeviceClass(DeviceClassId(params.value("deviceClassId").toString()));
foreach (const StateType &stateType, deviceClass.stateTypes()) {
stateList.append(packStateType(stateType, deviceClass.pluginId(), NymeaCore::instance()->configuration()->locale()));
foreach (StateType stateType, deviceClass.stateTypes()) {
stateType.setDisplayName(NymeaCore::instance()->deviceManager()->translate(deviceClass.pluginId(), stateType.displayName(), locale));
stateList.append(pack(stateType));
}
returns.insert("stateTypes", stateList);
return createReply(returns);
@ -908,7 +816,7 @@ Param DeviceHandler::unpackParam(const QVariantMap &param)
if (param.keys().count() == 0)
return Param();
ParamTypeId paramTypeId = param.value("paramTypeId").toString();
ParamTypeId paramTypeId = param.value("paramTypeId").toUuid();
QVariant value = param.value("value");
return Param(paramTypeId, value);
}
@ -992,56 +900,14 @@ QVariantMap DeviceHandler::packBrowserItem(const BrowserItem &item)
return ret;
}
QVariantMap DeviceHandler::packParamType(const ParamType &paramType, const PluginId &pluginId, const QLocale &locale)
QVariantMap DeviceHandler::packParamType(const ParamType &paramType, const PluginId &pluginId, const QLocale &locale) const
{
QVariantMap variantMap;
variantMap.insert("id", paramType.id().toString());
variantMap.insert("name", paramType.name());
variantMap.insert("displayName", NymeaCore::instance()->deviceManager()->translate(pluginId, paramType.displayName(), locale));
variantMap.insert("type", enumValueName<BasicType>(variantTypeToBasicType(paramType.type())));
variantMap.insert("index", paramType.index());
// Optional values
if (paramType.defaultValue().isValid())
variantMap.insert("defaultValue", paramType.defaultValue());
if (paramType.minValue().isValid())
variantMap.insert("minValue", paramType.minValue());
if (paramType.maxValue().isValid())
variantMap.insert("maxValue", paramType.maxValue());
if (!paramType.allowedValues().isEmpty())
variantMap.insert("allowedValues", paramType.allowedValues());
if (paramType.inputType() != Types::InputTypeNone)
variantMap.insert("inputType", enumValueName<Types::InputType>(paramType.inputType()));
if (paramType.unit() != Types::UnitNone)
variantMap.insert("unit", enumValueName<Types::Unit>(paramType.unit()));
if (paramType.readOnly())
variantMap.insert("readOnly", paramType.readOnly());
return variantMap;
ParamType translatedParamType = paramType;
translatedParamType.setDisplayName(NymeaCore::instance()->deviceManager()->translate(pluginId, paramType.displayName(), locale));
return pack(translatedParamType);
}
QVariantMap DeviceHandler::packPlugin(DevicePlugin *plugin, const QLocale &locale)
{
QVariantMap pluginMap;
pluginMap.insert("id", plugin->pluginId().toString());
pluginMap.insert("name", plugin->pluginName());
pluginMap.insert("displayName", NymeaCore::instance()->deviceManager()->translate(plugin->pluginId(), plugin->pluginDisplayName(), locale));
QVariantList params;
foreach (const ParamType &param, plugin->configurationDescription())
params.append(packParamType(param, plugin->pluginId(), locale));
pluginMap.insert("paramTypes", params);
return pluginMap;
}
QVariantMap DeviceHandler::packEventType(const EventType &eventType, const PluginId &pluginId, const QLocale &locale)
QVariantMap DeviceHandler::packEventType(const EventType &eventType, const PluginId &pluginId, const QLocale &locale) const
{
QVariantMap variant;
variant.insert("id", eventType.id().toString());
@ -1057,23 +923,7 @@ QVariantMap DeviceHandler::packEventType(const EventType &eventType, const Plugi
return variant;
}
QVariantMap DeviceHandler::packVendor(const Vendor &vendor, const QLocale &locale)
{
DevicePlugin *plugin = nullptr;
foreach (DevicePlugin *p, NymeaCore::instance()->deviceManager()->plugins()) {
if (p->supportedVendors().contains(vendor)) {
plugin = p;
}
}
QVariantMap variantMap;
variantMap.insert("id", vendor.id().toString());
variantMap.insert("name", vendor.name());
variantMap.insert("displayName", NymeaCore::instance()->deviceManager()->translate(plugin->pluginId(), vendor.displayName(), locale));
return variantMap;
}
QVariantMap DeviceHandler::packActionType(const ActionType &actionType, const PluginId &pluginId, const QLocale &locale)
QVariantMap DeviceHandler::packActionType(const ActionType &actionType, const PluginId &pluginId, const QLocale &locale) const
{
QVariantMap variantMap;
variantMap.insert("id", actionType.id().toString());
@ -1088,7 +938,7 @@ QVariantMap DeviceHandler::packActionType(const ActionType &actionType, const Pl
return variantMap;
}
QVariantList DeviceHandler::packCreateMethods(DeviceClass::CreateMethods createMethods)
QVariantList DeviceHandler::packCreateMethods(DeviceClass::CreateMethods createMethods) const
{
QVariantList ret;
if (createMethods.testFlag(DeviceClass::CreateMethodUser))
@ -1103,96 +953,6 @@ QVariantList DeviceHandler::packCreateMethods(DeviceClass::CreateMethods createM
return ret;
}
QVariantMap DeviceHandler::packDeviceClass(const DeviceClass &deviceClass, const QLocale &locale)
{
QVariantMap variant;
variant.insert("id", deviceClass.id().toString());
variant.insert("name", deviceClass.name());
variant.insert("displayName", NymeaCore::instance()->deviceManager()->translate(deviceClass.pluginId(), deviceClass.displayName(), locale));
variant.insert("vendorId", deviceClass.vendorId().toString());
variant.insert("pluginId", deviceClass.pluginId().toString());
variant.insert("interfaces", deviceClass.interfaces());
variant.insert("browsable", deviceClass.browsable());
QVariantList stateTypes;
foreach (const StateType &stateType, deviceClass.stateTypes())
stateTypes.append(packStateType(stateType, deviceClass.pluginId(), locale));
QVariantList eventTypes;
foreach (const EventType &eventType, deviceClass.eventTypes())
eventTypes.append(packEventType(eventType, deviceClass.pluginId(), locale));
QVariantList actionTypes;
foreach (const ActionType &actionType, deviceClass.actionTypes())
actionTypes.append(packActionType(actionType, deviceClass.pluginId(), locale));
QVariantList browserItemActionTypes;
foreach (const ActionType &actionType, deviceClass.browserItemActionTypes())
browserItemActionTypes.append(packActionType(actionType, deviceClass.pluginId(), locale));
QVariantList paramTypes;
foreach (const ParamType &paramType, deviceClass.paramTypes())
paramTypes.append(packParamType(paramType, deviceClass.pluginId(), locale));
QVariantList settingsTypes;
foreach (const ParamType &settingsType, deviceClass.settingsTypes())
settingsTypes.append(packParamType(settingsType, deviceClass.pluginId(), locale));
QVariantList discoveryParamTypes;
foreach (const ParamType &paramType, deviceClass.discoveryParamTypes())
discoveryParamTypes.append(packParamType(paramType, deviceClass.pluginId(), locale));
variant.insert("paramTypes", paramTypes);
variant.insert("settingsTypes", settingsTypes);
variant.insert("discoveryParamTypes", discoveryParamTypes);
variant.insert("stateTypes", stateTypes);
variant.insert("eventTypes", eventTypes);
variant.insert("actionTypes", actionTypes);
variant.insert("browserItemActionTypes", browserItemActionTypes);
variant.insert("createMethods", packCreateMethods(deviceClass.createMethods()));
variant.insert("setupMethod", enumValueName<DeviceClass::SetupMethod>(deviceClass.setupMethod()));
return variant;
}
QVariantMap DeviceHandler::packDeviceDescriptor(const DeviceDescriptor &descriptor)
{
QVariantMap variant;
variant.insert("id", descriptor.id().toString());
variant.insert("deviceId", descriptor.deviceId().toString());
variant.insert("title", descriptor.title());
variant.insert("description", descriptor.description());
QVariantList params;
foreach (const Param &param, descriptor.params()) {
params.append(packParam(param));
}
variant.insert("deviceParams", params);
return variant;
}
QVariantMap DeviceHandler::packStateType(const StateType &stateType, const PluginId &pluginId, const QLocale &locale)
{
QVariantMap variantMap;
variantMap.insert("id", stateType.id().toString());
variantMap.insert("name", stateType.name());
variantMap.insert("displayName", NymeaCore::instance()->deviceManager()->translate(pluginId, stateType.displayName(), locale));
variantMap.insert("index", stateType.index());
variantMap.insert("type", enumValueName(variantTypeToBasicType(stateType.type())));
variantMap.insert("defaultValue", stateType.defaultValue());
if (stateType.maxValue().isValid())
variantMap.insert("maxValue", stateType.maxValue());
if (stateType.minValue().isValid())
variantMap.insert("minValue", stateType.minValue());
if (!stateType.possibleValues().isEmpty())
variantMap.insert("possibleValues", stateType.possibleValues());
if(stateType.unit() != Types::UnitNone)
variantMap.insert("unit", enumValueName<Types::Unit>(stateType.unit()));
return variantMap;
}
void DeviceHandler::pluginConfigChanged(const PluginId &id, const ParamList &config)
{

View File

@ -60,15 +60,14 @@ public:
Q_INVOKABLE JsonReply *BrowseDevice(const QVariantMap &params) const;
Q_INVOKABLE JsonReply *GetBrowserItem(const QVariantMap &params) const;
static QVariantMap packParamType(const ParamType &paramType, const PluginId &pluginId, const QLocale &locale);
static QVariantMap packPlugin(DevicePlugin *plugin, const QLocale &locale);
static QVariantMap packVendor(const Vendor &vendor, const QLocale &locale);
static QVariantMap packEventType(const EventType &eventType, const PluginId &pluginId, const QLocale &locale);
static QVariantMap packStateType(const StateType &stateType, const PluginId &pluginId, const QLocale &locale);
static QVariantMap packActionType(const ActionType &actionType, const PluginId &pluginId, const QLocale &locale);
static QVariantList packCreateMethods(DeviceClass::CreateMethods createMethods);
static QVariantMap packDeviceClass(const DeviceClass &deviceClass, const QLocale &locale);
static QVariantMap packDeviceDescriptor(const DeviceDescriptor &descriptor);
QVariantMap packParamType(const ParamType &paramType, const PluginId &pluginId, const QLocale &locale) const;
// QVariantMap packPlugin(DevicePlugin *plugin, const QLocale &locale) const;
QVariantMap packEventType(const EventType &eventType, const PluginId &pluginId, const QLocale &locale) const;
// QVariantMap packStateType(const StateType &stateType, const PluginId &pluginId, const QLocale &locale) const;
QVariantMap packActionType(const ActionType &actionType, const PluginId &pluginId, const QLocale &locale) const;
QVariantList packCreateMethods(DeviceClass::CreateMethods createMethods) const;
// QVariantMap packDeviceClass(const DeviceClass &deviceClass, const QLocale &locale) const;
QVariantMap packDeviceDescriptor(const DeviceDescriptor &descriptor) const;
static QVariantMap packParam(const Param &param);
static QVariantList packParams(const ParamList &paramList);

View File

@ -48,12 +48,12 @@ namespace nymeaserver {
EventHandler::EventHandler(QObject *parent) :
JsonHandler(parent)
{
registerEnum<Types::InputType>();
registerEnum<Types::Unit>();
// Objects
QVariantMap event;
event.insert("eventTypeId", enumValueName(Uuid));
event.insert("deviceId", enumValueName(Uuid));
event.insert("o:params", QVariantList() << objectRef("Param"));
registerObject("Event", event);
registerObject<Param, ParamList>();
registerObject<Event>();
registerObject<ParamType, ParamTypes>();
// Methods
QString description; QVariantMap params; QVariantMap returns;
@ -80,30 +80,23 @@ QString EventHandler::name() const
void EventHandler::eventTriggered(const Event &event)
{
QVariantMap params;
QVariantMap variant;
variant.insert("eventTypeId", event.eventTypeId().toString());
variant.insert("deviceId", event.deviceId().toString());
QVariantList eventParams;
foreach (const Param &param, event.params()) {
eventParams.append(DeviceHandler::packParam(param));
}
variant.insert("params", eventParams);
params.insert("event", variant);
params.insert("event", pack(event));
emit EventTriggered(params);
}
JsonReply* EventHandler::GetEventType(const QVariantMap &params) const
{
QLocale locale = params.value("locale").toLocale();
qCDebug(dcJsonRpc) << "asked for event type" << params;
EventTypeId eventTypeId(params.value("eventTypeId").toString());
foreach (const DeviceClass &deviceClass, NymeaCore::instance()->deviceManager()->supportedDevices()) {
foreach (const EventType &eventType, deviceClass.eventTypes()) {
if (eventType.id() == eventTypeId) {
EventType translatedEventType = eventType;
translatedEventType.setDisplayName(NymeaCore::instance()->deviceManager()->translate(deviceClass.pluginId(), eventType.displayName(), locale));
QVariantMap data;
data.insert("deviceError", enumValueName<Device::DeviceError>(Device::DeviceErrorNoError));
data.insert("eventType", DeviceHandler::packEventType(eventType, deviceClass.pluginId(), params.value("locale").toLocale()));
data.insert("eventType", pack(translatedEventType));
return createReply(data);
}
}

View File

@ -80,12 +80,13 @@ JsonRPCServerImplementation::JsonRPCServerImplementation(const QSslConfiguration
registerEnum<CloudManager::CloudConnectionState>();
// Objects
QVariantMap tokenInfo;
tokenInfo.insert("id", enumValueName(Uuid));
tokenInfo.insert("userName", enumValueName(String));
tokenInfo.insert("deviceName", enumValueName(String));
tokenInfo.insert("creationTime", enumValueName(Uint));
registerObject("TokenInfo", tokenInfo);
// QVariantMap tokenInfo;
// tokenInfo.insert("id", enumValueName(Uuid));
// tokenInfo.insert("userName", enumValueName(String));
// tokenInfo.insert("deviceName", enumValueName(String));
// tokenInfo.insert("creationTime", enumValueName(Uint));
// registerObject("TokenInfo", tokenInfo);
registerObject<TokenInfo>();
// Methods
QString description; QVariantMap returns; QVariantMap params;
@ -355,14 +356,10 @@ JsonReply *JsonRPCServerImplementation::Tokens(const QVariantMap &params) const
QByteArray token = property("token").toByteArray();
QString username = NymeaCore::instance()->userManager()->userForToken(token);
if (username.isEmpty()) {
// There *really* should be a user for the token in the DB
Q_ASSERT(false);
}
QList<TokenInfo> tokens = NymeaCore::instance()->userManager()->tokens(username);
QVariantList retList;
foreach (const TokenInfo &tokenInfo, tokens) {
retList << packTokenInfo(tokenInfo);
retList << pack(tokenInfo);
}
QVariantMap retMap;
retMap.insert("tokenInfoList", retList);
@ -682,16 +679,6 @@ void JsonRPCServerImplementation::processJsonPacket(TransportInterface *interfac
}
}
QVariantMap JsonRPCServerImplementation::packTokenInfo(const TokenInfo &tokenInfo)
{
QVariantMap ret;
ret.insert("id", tokenInfo.id().toString());
ret.insert("userName", tokenInfo.username());
ret.insert("deviceName", tokenInfo.deviceName());
ret.insert("creationTime", tokenInfo.creationTime().toTime_t());
return ret;
}
void JsonRPCServerImplementation::sendNotification(const QVariantMap &params)
{
JsonHandler *handler = qobject_cast<JsonHandler *>(sender());
@ -793,39 +780,57 @@ void JsonRPCServerImplementation::onPushButtonAuthFinished(int transactionId, bo
bool JsonRPCServerImplementation::registerHandler(JsonHandler *handler)
{
// Sanity checks on API:
// * Make sure all $ref: entries are valid. A Handler can reference Types from previously loaded handlers or own ones.
// * A handler must not register a type name that is already registered by a previously loaded handler.
QVariantMap types = m_api.value("types").toMap();
// * Make sure all $ref: entries are valid.
// * A handler must not register a type name that is already registered by a previously loaded handler with different content.
QVariantMap methods = m_api.value("methods").toMap();
QVariantMap notifications = m_api.value("notifications").toMap();
QVariantMap apiIncludingThis = m_api;
// Verify enums name clash
QVariantMap enums = m_api.value("enums").toMap();
foreach (const QString &enumName, handler->jsonEnums().keys()) {
QVariantList list = handler->jsonEnums().value(enumName).toList();
if (types.contains(enumName)) {
if (enums.contains(enumName) && enums.value(enumName) != list) {
qCWarning(dcJsonRpc()) << "Enum type" << enumName << "is already registered. Not registering handler" << handler->name();
return false;
}
types.insert(enumName, list);
enums.insert(enumName, list);
}
apiIncludingThis["enums"] = enums;
QVariantMap flags = m_api.value("flags").toMap();
foreach (const QString &flagName, handler->jsonFlags().keys()) {
QVariant flagDescription = handler->jsonFlags().value(flagName);
if (enums.contains(flagName)) {
qCWarning(dcJsonRpc()) << "Enum with name" << flagName << "is already registered. Not registering handler" << handler->name();
return false;
}
if (flags.contains(flagName) && flags.value(flagName) != handler->jsonFlags().value(flagName)) {
qCWarning(dcJsonRpc()) << "Flags with name" << flagName << "is already registered. Not registering handler" << handler->name();
return false;
}
flags.insert(flagName, flagDescription);
}
apiIncludingThis["flags"] = flags;
// Verify objects
QVariantMap typesIncludingThis = types;
QVariantMap existingTypes = m_api.value("types").toMap();
QVariantMap typesIncludingThis = existingTypes;
typesIncludingThis.unite(handler->jsonObjects());
apiIncludingThis["types"] = typesIncludingThis;
foreach (const QString &objectName, handler->jsonObjects().keys()) {
QVariantMap object = handler->jsonObjects().value(objectName).toMap();
// Check for name clashes
if (types.contains(objectName)) {
if (existingTypes.contains(objectName) && existingTypes.value(objectName) != handler->jsonObjects().value(objectName)) {
qCWarning(dcJsonRpc()) << "Object type" << objectName << "is already registered. Not registering handler" << handler->name();
return false;
}
// Check for invalid $ref: entries
if (!JsonValidator::checkRefs(object, typesIncludingThis)) {
if (!JsonValidator::checkRefs(object, apiIncludingThis)) {
qCWarning(dcJsonRpc()).nospace() << "Invalid reference in object type " << objectName << ". Not registering handler " << handler->name();
return false;
}
}
types = typesIncludingThis;
// Verify methods
QVariantMap newMethods;
@ -835,35 +840,35 @@ bool JsonRPCServerImplementation::registerHandler(JsonHandler *handler)
qCWarning(dcJsonRpc()).nospace().noquote() << "Invalid method \"" << methodName << "\". Method \"JsonReply* " + methodName + "(QVariantMap)\" does not exist. Not registering handler " << handler->name();
return false;
}
if (!JsonValidator::checkRefs(method.value("params").toMap(), types)) {
if (!JsonValidator::checkRefs(method.value("params").toMap(), apiIncludingThis)) {
qCWarning(dcJsonRpc()).nospace() << "Invalid reference in params of method " << methodName << ". Not registering handler " << handler->name();
return false;
}
if (!JsonValidator::checkRefs(method.value("returns").toMap(), types)) {
if (!JsonValidator::checkRefs(method.value("returns").toMap(), apiIncludingThis)) {
qCWarning(dcJsonRpc()).nospace() << "Invalid reference in return value of method " << methodName << ". Not registering handler " << handler->name();
return false;
}
newMethods.insert(handler->name() + '.' + methodName, method);
}
methods.unite(newMethods);
apiIncludingThis["methods"] = methods;
// Verify notifications
QVariantMap newNotifications;
foreach (const QString &notificationName, handler->jsonNotifications().keys()) {
QVariantMap notification = handler->jsonNotifications().value(notificationName).toMap();
if (!JsonValidator::checkRefs(notification.value("params").toMap(), types)) {
if (!JsonValidator::checkRefs(notification.value("params").toMap(), apiIncludingThis)) {
qCWarning(dcJsonRpc()).nospace() << "Invalid reference in params of notification " << notificationName << ". Not registering handler " << handler->name();
return false;
}
newNotifications.insert(handler->name() + '.' + notificationName, notification);
}
notifications.unite(newNotifications);
apiIncludingThis["notifications"] = notifications;
// Checks completed. Store new API
qCDebug(dcJsonRpc()) << "Registering JSON RPC handler:" << handler->name();
m_api["types"] = types;
m_api["methods"] = methods;
m_api["notifications"] = notifications;
m_api = apiIncludingThis;
m_handlers.insert(handler->name(), handler);
for (int i = 0; i < handler->metaObject()->methodCount(); ++i) {

View File

@ -84,9 +84,6 @@ private:
void processJsonPacket(TransportInterface *interface, const QUuid &clientId, const QByteArray &data);
static QVariantMap packTokenInfo(const TokenInfo &tokenInfo);
private slots:
void setup();

View File

@ -9,18 +9,23 @@
namespace nymeaserver {
bool JsonValidator::checkRefs(const QVariantMap &map, const QVariantMap &types)
bool JsonValidator::checkRefs(const QVariantMap &map, const QVariantMap &api)
{
QVariantMap enums = api.value("enums").toMap();
QVariantMap flags = api.value("flags").toMap();
QVariantMap types = api.value("types").toMap();
// qWarning() << "checkrefs enums" << enums.keys();
foreach (const QString &key, map.keys()) {
// qWarning() << "checking prop" << key;
if (map.value(key).toString().startsWith("$ref:")) {
QString refName = map.value(key).toString().remove("$ref:");
if (!types.contains(refName)) {
if (!enums.contains(refName) && !flags.contains(refName) && !types.contains(refName)) {
qCWarning(dcJsonRpc()) << "Invalid reference to" << refName;
return false;
}
}
if (map.value(key).type() == QVariant::Map) {
bool ret = checkRefs(map.value(key).toMap(), types);
bool ret = checkRefs(map.value(key).toMap(), api);
if (!ret) {
return false;
}
@ -29,13 +34,13 @@ bool JsonValidator::checkRefs(const QVariantMap &map, const QVariantMap &types)
foreach (const QVariant &entry, map.value(key).toList()) {
if (entry.toString().startsWith("$ref:")) {
QString refName = entry.toString().remove("$ref:");
if (!types.contains(refName)) {
if (!enums.contains(refName) && !flags.contains(refName) && !types.contains(refName)) {
qCWarning(dcJsonRpc()) << "Invalid reference to" << refName;
return false;
}
}
if (entry.type() == QVariant::Map) {
bool ret = checkRefs(map.value(key).toMap(), types);
bool ret = checkRefs(map.value(key).toMap(), api);
if (!ret) {
return false;
}
@ -50,7 +55,7 @@ bool JsonValidator::checkRefs(const QVariantMap &map, const QVariantMap &types)
JsonValidator::Result JsonValidator::validateParams(const QVariantMap &params, const QString &method, const QVariantMap &api)
{
QVariantMap paramDefinition = api.value("methods").toMap().value(method).toMap().value("params").toMap();
m_result = validateMap(params, paramDefinition, api.value("types").toMap());
m_result = validateMap(params, paramDefinition, api);
m_result.setWhere(method + ", param " + m_result.where());
return m_result;
}
@ -58,7 +63,7 @@ JsonValidator::Result JsonValidator::validateParams(const QVariantMap &params, c
JsonValidator::Result JsonValidator::validateReturns(const QVariantMap &returns, const QString &method, const QVariantMap &api)
{
QVariantMap returnsDefinition = api.value("methods").toMap().value(method).toMap().value("returns").toMap();
m_result = validateMap(returns, returnsDefinition, api.value("types").toMap());
m_result = validateMap(returns, returnsDefinition, api);
m_result.setWhere(method + ", returns " + m_result.where());
return m_result;
}
@ -66,7 +71,7 @@ JsonValidator::Result JsonValidator::validateReturns(const QVariantMap &returns,
JsonValidator::Result JsonValidator::validateNotificationParams(const QVariantMap &params, const QString &notification, const QVariantMap &api)
{
QVariantMap paramDefinition = api.value("notifications").toMap().value(notification).toMap().value("params").toMap();
m_result = validateMap(params, paramDefinition, api.value("types").toMap());
m_result = validateMap(params, paramDefinition, api);
m_result.setWhere(notification + ", param " + m_result.where());
return m_result;
}
@ -76,7 +81,7 @@ JsonValidator::Result JsonValidator::result() const
return m_result;
}
JsonValidator::Result JsonValidator::validateMap(const QVariantMap &map, const QVariantMap &definition, const QVariantMap &types)
JsonValidator::Result JsonValidator::validateMap(const QVariantMap &map, const QVariantMap &definition, const QVariantMap &api)
{
// Make sure all required values are available
foreach (const QString &key, definition.keys()) {
@ -102,7 +107,7 @@ JsonValidator::Result JsonValidator::validateMap(const QVariantMap &map, const Q
// Validate content
QVariant value = map.value(key);
Result result = validateEntry(value, expectedValue, types);
Result result = validateEntry(value, expectedValue, api);
if (!result.success()) {
result.setWhere(key + '.' + result.where());
result.setErrorString(result.errorString());
@ -114,8 +119,11 @@ JsonValidator::Result JsonValidator::validateMap(const QVariantMap &map, const Q
return Result(true);
}
JsonValidator::Result JsonValidator::validateEntry(const QVariant &value, const QVariant &definition, const QVariantMap &types)
JsonValidator::Result JsonValidator::validateEntry(const QVariant &value, const QVariant &definition, const QVariantMap &api)
{
// qWarning() << "validating" << definition;
// qWarning() << "** enums:" << api.value("enums").toMap().keys();
// qWarning() << "** types:" << api.value("types").toMap().keys();
if (definition.type() == QVariant::String) {
QString expectedTypeName = definition.toString();
@ -123,20 +131,39 @@ JsonValidator::Result JsonValidator::validateEntry(const QVariant &value, const
QString refName = expectedTypeName;
refName.remove("$ref:");
QVariant refDefinition = types.value(refName);
// Refs might be enums
if (refDefinition.type() == QVariant::List) {
if (value.type() != QVariant::String) {
return Result(false, "Expected enum " + refName + " but got " + value.toString());
}
QVariantMap enums = api.value("enums").toMap();
if (enums.contains(refName)) {
QVariant refDefinition = enums.value(refName);
QVariantList enumList = refDefinition.toList();
if (!enumList.contains(value.toString())) {
return Result(false, "Expected enum " + refName + " but got " + value.toString());
return Result(false, "Expected enum " + refName + " but got " + value.toJsonDocument().toJson());
}
return Result(true);
}
// Or flags
QVariantMap flags = api.value("flags").toMap();
if (flags.contains(refName)) {
QVariant refDefinition = flags.value(refName);
qWarning() << "Flag:" << value.type();
if (value.type() != QVariant::StringList) {
return Result(false, "Expected flags " + refName + " but got " + value.toString());
}
QString flagEnum = refDefinition.toList().first().toString();
qWarning() << "Flag enum:" << flagEnum;
foreach (const QVariant &flagsEntry, value.toList()) {
Result result = validateEntry(flagsEntry, flagEnum, api);
if (!result.success()) {
return result;
}
}
return Result(true);
}
return validateEntry(value, refDefinition, types);
QVariantMap types = api.value("types").toMap();
QVariant refDefinition = types.value(refName);
return validateEntry(value, refDefinition, api);
}
JsonHandler::BasicType expectedBasicType = JsonHandler::enumNameToValue<JsonHandler::BasicType>(expectedTypeName);
@ -199,7 +226,7 @@ JsonValidator::Result JsonValidator::validateEntry(const QVariant &value, const
if (value.type() != QVariant::Map) {
return Result(false, "Invalud value. Expected a map bug received: " + value.toString());
}
return validateMap(value.toMap(), definition.toMap(), types);
return validateMap(value.toMap(), definition.toMap(), api);
}
if (definition.type() == QVariant::List) {
@ -209,7 +236,7 @@ JsonValidator::Result JsonValidator::validateEntry(const QVariant &value, const
return Result(false, "Expected list of " + entryDefinition.toString() + " but got value of type " + value.typeName() + "\n" + QJsonDocument::fromVariant(value).toJson());
}
foreach (const QVariant &entry, value.toList()) {
Result result = validateEntry(entry, entryDefinition, types);
Result result = validateEntry(entry, entryDefinition, api);
if (!result.success()) {
return result;
}

View File

@ -30,7 +30,7 @@ public:
JsonValidator() {}
static bool checkRefs(const QVariantMap &map, const QVariantMap &types);
static bool checkRefs(const QVariantMap &map, const QVariantMap &api);
Result validateParams(const QVariantMap &params, const QString &method, const QVariantMap &api);
Result validateReturns(const QVariantMap &returns, const QString &method, const QVariantMap &api);
@ -38,8 +38,8 @@ public:
Result result() const;
private:
Result validateMap(const QVariantMap &map, const QVariantMap &definition, const QVariantMap &types);
Result validateEntry(const QVariant &value, const QVariant &definition, const QVariantMap &types);
Result validateMap(const QVariantMap &map, const QVariantMap &definition, const QVariantMap &api);
Result validateEntry(const QVariant &value, const QVariant &definition, const QVariantMap &api);
Result m_result;
};

View File

@ -62,18 +62,7 @@ LoggingHandler::LoggingHandler(QObject *parent) :
registerEnum<Logging::LoggingError>();
// Objects
QVariantMap logEntry;
logEntry.insert("timestamp", enumValueName(Int));
logEntry.insert("loggingLevel", enumRef<Logging::LoggingLevel>());
logEntry.insert("source", enumRef<Logging::LoggingSource>());
logEntry.insert("o:typeId", enumValueName(Uuid));
logEntry.insert("o:deviceId", enumValueName(Uuid));
logEntry.insert("o:itemId", enumValueName(String));
logEntry.insert("o:value", enumValueName(String));
logEntry.insert("o:active", enumValueName(Bool));
logEntry.insert("o:eventType", enumRef<Logging::LoggingEventType>());
logEntry.insert("o:errorCode", enumValueName(String));
registerObject("LogEntry", logEntry);
registerObject<LogEntry>();
// Methods
QString description; QVariantMap params; QVariantMap returns;
@ -198,8 +187,8 @@ QVariantMap LoggingHandler::packLogEntry(const LogEntry &logEntry)
case Logging::LoggingSourceActions:
case Logging::LoggingSourceEvents:
case Logging::LoggingSourceStates:
logEntryMap.insert("typeId", logEntry.typeId().toString());
logEntryMap.insert("deviceId", logEntry.deviceId().toString());
logEntryMap.insert("typeId", logEntry.typeId());
logEntryMap.insert("deviceId", logEntry.deviceId());
logEntryMap.insert("value", LogValueTool::convertVariantToString(logEntry.value()));
break;
case Logging::LoggingSourceSystem:

View File

@ -116,12 +116,7 @@ RulesHandler::RulesHandler(QObject *parent) :
repeatingOption.insert("o:monthDays", QVariantList() << enumValueName(Int));
registerObject("RepeatingOption", repeatingOption);
QVariantMap calendarItem;
calendarItem.insert("o:datetime", enumValueName(Uint));
calendarItem.insert("o:startTime", enumValueName(Time));
calendarItem.insert("duration", enumValueName(Uint));
calendarItem.insert("o:repeating", objectRef("RepeatingOption"));
registerObject("CalendarItem", calendarItem);
registerObject<CalendarItem>();
QVariantMap timeEventItem;
timeEventItem.insert("o:datetime", enumValueName(Uint));

View File

@ -73,7 +73,8 @@ JsonReply* StateHandler::GetStateType(const QVariantMap &params) const
if (stateType.id() == stateTypeId) {
QVariantMap data;
data.insert("deviceError", enumValueName<Device::DeviceError>(Device::DeviceErrorNoError));
data.insert("stateType", DeviceHandler::packStateType(stateType, deviceClass.pluginId(), params.value("locale").toLocale()));
// FIXME TODO!!!
// data.insert("stateType", DeviceHandler::packStateType(stateType, deviceClass.pluginId(), params.value("locale").toLocale()));
return createReply(data);
}
}

View File

@ -34,6 +34,16 @@ namespace nymeaserver {
class LogEntry
{
Q_GADGET
Q_PROPERTY(QDateTime timestamp READ timestamp)
Q_PROPERTY(Logging::LoggingLevel loggingLevel READ level)
Q_PROPERTY(Logging::LoggingSource source READ source)
Q_PROPERTY(QUuid typeId READ typeId USER true)
Q_PROPERTY(QUuid deviceId READ deviceId USER true)
// Q_PROPERTY(QString itemId READ itemId USER true)
Q_PROPERTY(QVariant value READ value USER true)
Q_PROPERTY(bool active READ active USER true)
Q_PROPERTY(Logging::LoggingEventType eventType READ eventType USER true)
Q_PROPERTY(QString errorCode READ errorCode USER true)
public:
LogEntry(QDateTime timestamp, Logging::LoggingLevel level, Logging::LoggingSource source, int errorCode = 0);

View File

@ -30,9 +30,16 @@
namespace nymeaserver {
class ServerConfiguration {
Q_GADGET
Q_PROPERTY(QString id MEMBER id)
Q_PROPERTY(QString address READ addressString)
Q_PROPERTY(uint port MEMBER port)
Q_PROPERTY(bool sslEnabled MEMBER sslEnabled)
Q_PROPERTY(bool authenticationEnabled MEMBER authenticationEnabled)
public:
QString id;
QHostAddress address;
QString addressString() { return address.toString(); }
uint port = 0;
bool sslEnabled = true;
bool authenticationEnabled = true;
@ -50,6 +57,8 @@ QDebug operator <<(QDebug debug, const ServerConfiguration &configuration);
class WebServerConfiguration: public ServerConfiguration
{
Q_GADGET
Q_PROPERTY(QString publicFolder MEMBER publicFolder)
public:
QString publicFolder;
bool restServerEnabled = false;
@ -57,6 +66,13 @@ public:
class MqttPolicy
{
Q_GADGET
Q_PROPERTY(QString clientId MEMBER clientId)
Q_PROPERTY(QString username MEMBER username)
Q_PROPERTY(QString password MEMBER password)
Q_PROPERTY(QStringList allowedPublishTopicFilters MEMBER allowedPublishTopicFilters)
Q_PROPERTY(QStringList allowedSubscribeTopicFilters MEMBER allowedSubscribeTopicFilters)
public:
QString clientId;
QString username;

View File

@ -23,11 +23,18 @@
#include <QUuid>
#include <QDateTime>
#include <QMetaObject>
namespace nymeaserver {
class TokenInfo
{
Q_GADGET
Q_PROPERTY(QUuid id READ id)
Q_PROPERTY(QString username READ username)
Q_PROPERTY(QDateTime createionTime READ creationTime)
Q_PROPERTY(QString deviveName READ deviceName)
public:
TokenInfo(const QUuid &id, const QString &username, const QDateTime &creationTime, const QString &deviceName);

View File

@ -41,9 +41,14 @@ class DevicePlugin;
class LIBNYMEA_EXPORT Device: public QObject
{
Q_OBJECT
friend class DeviceManager;
friend class DeviceManagerImplementation;
Q_PROPERTY(QUuid id READ id)
Q_PROPERTY(QUuid deviceClassId READ deviceClassId)
Q_PROPERTY(QString name READ name WRITE setName NOTIFY nameChanged)
Q_PROPERTY(ParamList params READ params WRITE setParams)
Q_PROPERTY(ParamList settings READ settings WRITE setSettings)
Q_PROPERTY(States states READ states WRITE setStates)
Q_PROPERTY(bool setupComplete READ setupComplete WRITE setSetupComplete)
Q_PROPERTY(QUuid parentId READ parentId WRITE setParentId USER true)
public:
enum DeviceError {
@ -122,6 +127,8 @@ signals:
void nameChanged();
private:
friend class DeviceManager;
friend class DeviceManagerImplementation;
Device(DevicePlugin *plugin, const DeviceClass &deviceClass, const DeviceId &id, QObject *parent = nullptr);
Device(DevicePlugin *plugin, const DeviceClass &deviceClass, QObject *parent = nullptr);

View File

@ -32,6 +32,13 @@
class LIBNYMEA_EXPORT DeviceDescriptor
{
Q_GADGET
Q_PROPERTY(QUuid id READ id)
Q_PROPERTY(QUuid deviceId READ deviceId USER true)
Q_PROPERTY(QString title READ title)
Q_PROPERTY(QString description READ description)
Q_PROPERTY(ParamList deviceParams READ params)
public:
DeviceDescriptor();
DeviceDescriptor(const DeviceClassId &deviceClassId, const QString &title = QString(), const QString &description = QString(), const DeviceId &parentDeviceId = DeviceId());

View File

@ -125,7 +125,9 @@ public:
virtual BrowserItemActionInfo* executeBrowserItemAction(const BrowserItemAction &browserItemAction) = 0;
virtual QString translate(const PluginId &pluginId, const QString &string, const QLocale &locale) = 0;
virtual ParamType translateParamType(const PluginId &pluginId, const ParamType &paramType, const QLocale &locale) = 0;
virtual DeviceClass translateDeviceClass(const DeviceClass &deviceClass, const QLocale &locale) = 0;
virtual Vendor translateVendor(const Vendor &vendor, const QLocale &locale) = 0;
signals:
void pluginConfigChanged(const PluginId &id, const ParamList &config);
void eventTriggered(const Event &event);

View File

@ -62,8 +62,10 @@ class LIBNYMEA_EXPORT DevicePlugin: public QObject
{
Q_OBJECT
friend class DeviceManager;
friend class DeviceManagerImplementation;
Q_PROPERTY(QUuid id READ pluginId)
Q_PROPERTY(QString name READ pluginName)
Q_PROPERTY(QString displayName READ pluginDisplayName)
Q_PROPERTY(ParamTypes paramTypes READ configurationDescription)
public:
DevicePlugin(QObject *parent = nullptr);
@ -115,6 +117,10 @@ protected:
QSettings *pluginStorage() const;
private:
friend class DeviceManager;
friend class DeviceManagerImplementation;
void setMetaData(const PluginMetadata &metaData);
void initPlugin(const PluginMetadata &metadata, DeviceManager *deviceManager, HardwareManager *hardwareManager);

View File

@ -103,7 +103,7 @@ void PluginMetadata::parse(const QJsonObject &jsonObject)
return;
}
m_pluginId = jsonObject.value("id").toString();
m_pluginId = PluginId(jsonObject.value("id").toString());
m_pluginName = jsonObject.value("name").toString();
m_pluginDisplayName = jsonObject.value("displayName").toString();
@ -192,7 +192,7 @@ void PluginMetadata::parse(const QJsonObject &jsonObject)
continue;
}
DeviceClassId deviceClassId = deviceClassObject.value("id").toString();
DeviceClassId deviceClassId = DeviceClassId(deviceClassObject.value("id").toString());
QString deviceClassName = deviceClassObject.value("name").toString();
// Check if there are any unknown fields
@ -304,7 +304,7 @@ void PluginMetadata::parse(const QJsonObject &jsonObject)
continue;
}
StateTypeId stateTypeId = st.value("id").toString();
StateTypeId stateTypeId = StateTypeId(st.value("id").toString());
QString stateTypeName = st.value("name").toString();
// Check if there are any unknown fields

View File

@ -6,6 +6,7 @@
JsonHandler::JsonHandler(QObject *parent) : QObject(parent)
{
registerEnum<BasicType>();
}
QVariantMap JsonHandler::jsonEnums() const
@ -13,6 +14,11 @@ QVariantMap JsonHandler::jsonEnums() const
return m_enums;
}
QVariantMap JsonHandler::jsonFlags() const
{
return m_flags;
}
QVariantMap JsonHandler::jsonObjects() const
{
return m_objects;
@ -62,6 +68,8 @@ JsonHandler::BasicType JsonHandler::variantTypeToBasicType(QVariant::Type varian
return Time;
case QVariant::Map:
return Object;
case QVariant::DateTime:
return Uint; // DateTime is represented as time_t
default:
return Variant;
}
@ -132,3 +140,73 @@ JsonReply *JsonHandler::createAsyncReply(const QString &method) const
return JsonReply::createAsyncReply(const_cast<JsonHandler*>(this), method);
}
QVariantMap JsonHandler::pack(const QMetaObject &metaObject, const void *value) const
{
QVariantMap ret;
// qWarning() << "+ Packing" << metaObject.className();
for (int i = 0; i < metaObject.propertyCount(); i++) {
QMetaProperty metaProperty = metaObject.property(i);
if (metaProperty.name() == QStringLiteral("objectName")) {
continue; // Skip QObject's objectName property
}
QVariant val = metaProperty.readOnGadget(value);
// qWarning() << "|- Property:" << metaProperty.name() << metaProperty.readOnGadget(value) << metaProperty.type() << metaProperty.typeName();
// qWarning() << "|-- All list types:" << m_listMetaObjects.keys();
if (metaProperty.type() == QVariant::UserType) {
if (metaProperty.typeName() == QStringLiteral("QVariant::Type")) {
QMetaEnum metaEnum = QMetaEnum::fromType<BasicType>();
// qWarning() << "|--" << metaProperty.readOnGadget(value).toInt() << metaEnum.key(metaProperty.readOnGadget(value).toInt());
ret.insert(metaProperty.name(), metaEnum.key(variantTypeToBasicType(metaProperty.readOnGadget(value).template value<QVariant::Type>())));
} else if (m_listMetaObjects.contains(metaProperty.typeName())) {
QVariant listObject = metaProperty.readOnGadget(value);
QMetaObject listMetaObject = m_listMetaObjects.value(metaProperty.typeName());
QMetaProperty countProperty = listMetaObject.property(listMetaObject.indexOfProperty("count"));
int listCount = countProperty.readOnGadget(listObject.constData()).toInt();
// qWarning() << "Packing list type" << listObject << "count is" << listCount;
QMetaMethod metaMethod = listMetaObject.method(listMetaObject.indexOfMethod("get(int)"));
// qWarning() << "get method" << listMetaObject.indexOfMethod("get(int)") << listMetaObject.method(0).name() << QMetaObject::normalizedSignature("QVariant get(int)");
QMetaObject entryMetaObject = m_metaObjects.value(m_listEntryTypes.value(listMetaObject.className()));
QVariantList list;
for (int i = 0; i < listCount; i++) {
QVariant entry;
metaMethod.invokeOnGadget(listObject.data(), Q_RETURN_ARG(QVariant, entry), Q_ARG(int, i));
// qWarning() << "|---Feckin hell" << entry;
list.append(pack(entryMetaObject, entry.data()));
}
ret.insert(metaProperty.name(), list);
} else {
Q_ASSERT_X(false, this->metaObject()->className(), QString("Cannot pack %1. %2 is not registered in this handler.").arg(metaObject.className()).arg(metaProperty.typeName()).toUtf8());
}
} else if (metaProperty.isFlagType()) {
QMetaEnum metaFlag = m_metaFlags.value(QString(metaProperty.typeName()).split("::").last());
// QMetaEnum metaEnum = m_metaEnums.value(m_flagsEnums.value(metaFlag.name()));
int flagValue = metaProperty.readOnGadget(value).toInt();
// qWarning() << "|-- Flag" << flagValue << metaFlag.name() << metaFlag.keyCount() << metaProperty.type();
QStringList flags;
for (int i = 0; i < metaFlag.keyCount(); i++) {
// qWarning() << "|--- flag key:" << metaFlag.key(i) << metaFlag.value(i);
if ((metaFlag.value(i) & flagValue) > 0) {
flags.append(metaFlag.key(i));
}
}
ret.insert(metaProperty.name(), flags);
} else if (metaProperty.isEnumType()) {
QString enumName = QString(metaProperty.typeName()).split("::").last();
Q_ASSERT_X(m_metaEnums.contains(enumName), this->metaObject()->className(), QString("Cannot pack %1. %2 is not registered int this handler.").arg(metaObject.className()).arg(metaProperty.typeName()).toUtf8());
QMetaEnum metaEnum = m_metaEnums.value(enumName);
// qWarning() << "|-- Enum: Name:" << metaEnum.name() << "as int:" << metaEnum.key(metaProperty.readOnGadget(value).toInt()) << "All enums:" << m_metaEnums.keys();
ret.insert(metaProperty.name(), metaEnum.key(metaProperty.readOnGadget(value).toInt()));
} else if (!metaProperty.isUser() || !metaProperty.readOnGadget(value).isNull()) {
// qWarning() << "|-- property" << metaProperty.name() << metaProperty.readOnGadget(value);
ret.insert(metaProperty.name(), metaProperty.readOnGadget(value));
}
}
return ret;
}

View File

@ -4,6 +4,8 @@
#include <QObject>
#include <QVariantMap>
#include <QMetaMethod>
#include <QDebug>
#include <QVariant>
#include "jsonreply.h"
@ -32,6 +34,7 @@ public:
virtual QString name() const = 0;
QVariantMap jsonEnums() const;
QVariantMap jsonFlags() const;
QVariantMap jsonObjects() const;
QVariantMap jsonMethods() const;
QVariantMap jsonNotifications() const;
@ -46,8 +49,13 @@ public:
static BasicType variantTypeToBasicType(QVariant::Type variantType);
static QVariant::Type basicTypeToVariantType(BasicType basicType);
template<typename T> QVariantMap pack(const T &value) const;
protected:
template <typename T> void registerEnum();
template <typename Enum> void registerEnum();
template <typename Enum, typename Flags> void registerEnum();
template <typename ObjectType> void registerObject();
template <typename ObjectType, typename ListType> void registerObject();
void registerObject(const QString &name, const QVariantMap &object);
void registerMethod(const QString &name, const QString &description, const QVariantMap &params, const QVariantMap &returns, bool deprecated = false);
void registerNotification(const QString &name, const QString &description, const QVariantMap &params, bool deprecated = false);
@ -55,13 +63,23 @@ protected:
JsonReply *createReply(const QVariantMap &data) const;
JsonReply *createAsyncReply(const QString &method) const;
private:
QVariantMap pack(const QMetaObject &metaObject, const void *gadget) const;
private:
QVariantMap m_enums;
QHash<QString, QMetaEnum> m_metaEnums;
QVariantMap m_flags;
QHash<QString, QMetaEnum> m_metaFlags;
QHash<QString, QString> m_flagsEnums;
QVariantMap m_objects;
QHash<QString, QMetaObject> m_metaObjects;
QHash<QString, QMetaObject> m_listMetaObjects;
QHash<QString, QString> m_listEntryTypes;
QVariantMap m_methods;
QVariantMap m_notifications;
};
Q_DECLARE_METATYPE(QVariant::Type)
template<typename T>
void JsonHandler::registerEnum()
@ -72,9 +90,83 @@ void JsonHandler::registerEnum()
values << metaEnum.key(i);
}
m_enums.insert(metaEnum.name(), values);
m_metaEnums.insert(metaEnum.name(), metaEnum);
}
template<typename Enum, typename Flags>
void JsonHandler::registerEnum()
{
registerEnum<Enum>();
QMetaEnum metaEnum = QMetaEnum::fromType<Enum>();
QMetaEnum metaFlags = QMetaEnum::fromType<Flags>();
m_metaFlags.insert(metaFlags.name(), metaFlags);
m_flagsEnums.insert(metaFlags.name(), metaEnum.name());
m_flags.insert(metaFlags.name(), QVariantList() << QString("$ref:%1").arg(metaEnum.name()));
}
template<typename ObjectType>
void JsonHandler::registerObject()
{
qRegisterMetaType<QVariant::Type>();
QMetaObject metaObject = ObjectType::staticMetaObject;
QString className = QString(metaObject.className()).split("::").last();
QVariantMap description;
for (int i = 0; i < metaObject.propertyCount(); i++) {
QMetaProperty metaProperty = metaObject.property(i);
QString name = metaProperty.name();
if (name == "objectName") {
continue; // Skip QObject's objectName property
}
if (metaProperty.isUser()) {
name.prepend("o:");
}
QVariant typeName;
// qWarning() << ".-.-.-.-.-" << metaProperty.name() << metaProperty.type() << metaProperty.typeName();
if (metaProperty.type() == QVariant::UserType) {
if (metaProperty.typeName() == QStringLiteral("QVariant::Type")) {
typeName = QString("$ref:BasicType");
} else if (QString(metaProperty.typeName()).startsWith("QList")) {
typeName = QVariantList() << "$ref:" + QString(metaProperty.typeName()).remove("QList<").remove(">");
} else {
typeName = QString("$ref:%1").arg(QString(metaProperty.typeName()).split("::").last());
}
} else if (metaProperty.isEnumType()) {
typeName = QString("$ref:%1").arg(QString(metaProperty.typeName()).split("::").last());
} else if (metaProperty.isFlagType()) {
typeName = QVariantList() << "$ref:" + m_flagsEnums.value(metaProperty.name());
} else if (metaProperty.type() == QVariant::List) {
typeName = QVariantList() << enumValueName(Variant);
} else {
typeName = enumValueName(variantTypeToBasicType(metaProperty.type()));
}
description.insert(name, typeName);
}
m_objects.insert(className, description);
m_metaObjects.insert(className, metaObject);
}
template<typename ObjectType, typename ListType>
void JsonHandler::registerObject()
{
registerObject<ObjectType>();
QMetaObject metaObject = ObjectType::staticMetaObject;
QMetaObject listMetaObject = ListType::staticMetaObject;
m_objects.insert(listMetaObject.className(), QVariantList() << QVariant(QString("$ref:%1").arg(metaObject.className())));
m_metaObjects.insert(listMetaObject.className(), listMetaObject);
m_listMetaObjects.insert(listMetaObject.className(), listMetaObject);
m_listEntryTypes.insert(listMetaObject.className(), metaObject.className());
Q_ASSERT_X(listMetaObject.indexOfProperty("count") >= 0, "JsonHandler", "List type does not implement \"count\" property!");
Q_ASSERT_X(listMetaObject.indexOfMethod("get(int)") >= 0, "JsonHandler", "List type does not implement \"Q_INVOKABLE QVariant get(int index)\" method!");
}
//template<typename T>
//void JsonHandler::registerList()
//{
// QMetaObject metaObject = T::staticMetaObject;
// m_lists.insert(metaObject.className(), metaObject);
// m_objects.insert(metaObject.classInfo(), QVariantList() << )
//}
template<typename T>
QString JsonHandler::enumRef()
{
@ -96,4 +188,12 @@ T JsonHandler::enumNameToValue(const QString &name)
return static_cast<T>(metaEnum.keyToValue(name.toUtf8()));
}
template<typename T>
QVariantMap JsonHandler::pack(const T &value) const
{
QMetaObject metaObject = T::staticMetaObject;
return pack(metaObject, static_cast<const void*>(&value));
}
#endif // JSONHANDLER_H

View File

@ -26,8 +26,7 @@ HEADERS += \
devices/browseresult.h \
jsonrpc/jsonhandler.h \
jsonrpc/jsonreply.h \
experiences/experienceplugin.h \
jsonrpc/jsonrpcserver.h \
jsonrpc/jsonrpcserver.h \
libnymea.h \
platform/package.h \
platform/repository.h \
@ -109,8 +108,7 @@ SOURCES += \
devices/browseresult.cpp \
jsonrpc/jsonhandler.cpp \
jsonrpc/jsonreply.cpp \
experiences/experienceplugin.cpp \
jsonrpc/jsonrpcserver.cpp \
jsonrpc/jsonrpcserver.cpp \
loggingcategories.cpp \
nymeasettings.cpp \
platform/package.cpp \

View File

@ -19,8 +19,8 @@
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/*!
\class nymeaserver::CalendarItem
\brief Describes a clendar item for a time based \l{nymeaserver::Rule}{Rule}.
\class CalendarItem
\brief Describes a clendar item.
\ingroup rules
\inmodule core
@ -33,8 +33,6 @@
#include <QDebug>
namespace nymeaserver {
/*! Construct a invalid \l{CalendarItem}. */
CalendarItem::CalendarItem():
m_duration(0)
@ -275,5 +273,4 @@ QDebug operator<<(QDebug dbg, const CalendarItem &calendarItem)
return dbg;
}
}

View File

@ -25,10 +25,13 @@
#include "repeatingoption.h"
namespace nymeaserver {
class CalendarItem
{
Q_GADGET
Q_PROPERTY(uint duration READ duration WRITE setDuration)
Q_PROPERTY(QDateTime datetime READ dateTime WRITE setDateTime USER true)
Q_PROPERTY(QTime startTime READ startTime WRITE setStartTime USER true)
Q_PROPERTY(RepeatingOption repeating READ repeatingOption WRITE setRepeatingOption USER true)
public:
CalendarItem();
@ -64,6 +67,5 @@ private:
};
QDebug operator<<(QDebug dbg, const CalendarItem &calendarItem);
}
#endif // CALENDARITEM_H

View File

@ -83,8 +83,6 @@
#include <QDateTime>
namespace nymeaserver {
/*! Constructs an empty \l{RepeatingOption}. */
RepeatingOption::RepeatingOption() :
m_mode(RepeatingModeNone)
@ -197,5 +195,3 @@ QDebug operator<<(QDebug dbg, const RepeatingOption &repeatingOption)
dbg.nospace() << "RepeatingOption(Mode:" << repeatingOption.mode() << ", Monthdays:" << repeatingOption.monthDays() << "Weekdays:" << repeatingOption.weekDays() << ")";
return dbg;
}
}

View File

@ -26,8 +26,6 @@
class QDateTime;
namespace nymeaserver {
class RepeatingOption
{
Q_GADGET
@ -66,6 +64,5 @@ private:
};
QDebug operator<<(QDebug dbg, const RepeatingOption &RepeatingOption);
}
#endif // REPEATINGOPTION_H

View File

@ -36,8 +36,6 @@
#include <QDebug>
namespace nymeaserver {
/*! Constructs an invalid \l{TimeDescriptor}.*/
TimeDescriptor::TimeDescriptor()
{
@ -119,5 +117,3 @@ QDebug operator<<(QDebug dbg, const TimeDescriptor &timeDescriptor)
}
return dbg;
}
}

View File

@ -24,8 +24,6 @@
#include "timeeventitem.h"
#include "calendaritem.h"
namespace nymeaserver {
class TimeDescriptor
{
public:
@ -54,6 +52,5 @@ private:
QDebug operator<<(QDebug dbg, const TimeDescriptor &timeDescriptor);
}
#endif // TIMEDESCRIPTOR_H

View File

@ -33,8 +33,6 @@
#include <QDebug>
namespace nymeaserver {
/*! Constructs an invalid \l{TimeEventItem}. */
TimeEventItem::TimeEventItem()
{
@ -141,4 +139,3 @@ QDebug operator<<(QDebug dbg, const TimeEventItem &timeEventItem)
return dbg;
}
}

View File

@ -25,8 +25,6 @@
#include "repeatingoption.h"
namespace nymeaserver {
class TimeEventItem
{
public:
@ -56,6 +54,5 @@ private:
QDebug operator<<(QDebug dbg, const TimeEventItem &timeEventItem);
}
#endif // TIMEEVENTITEM_H

View File

@ -73,12 +73,22 @@ ActionTypeId Action::actionTypeId() const
return m_actionTypeId;
}
void Action::setActionTypeId(const ActionTypeId &actionTypeId)
{
m_actionTypeId = actionTypeId;
}
/*! Returns the deviceId this Action is associated with. */
DeviceId Action::deviceId() const
{
return m_deviceId;
}
void Action::setDeviceId(const DeviceId &deviceId)
{
m_deviceId = deviceId;
}
/*! Returns the parameters for this Action. */
ParamList Action::params() const
{

View File

@ -32,6 +32,11 @@
class LIBNYMEA_EXPORT Action
{
Q_GADGET
Q_PROPERTY(QUuid actionTypeId READ actionTypeId WRITE setActionTypeId)
Q_PROPERTY(QUuid deviceId READ deviceId WRITE setDeviceId)
Q_PROPERTY(ParamList params READ params WRITE setParams USER true)
public:
explicit Action(const ActionTypeId &actionTypeId = ActionTypeId(), const DeviceId &deviceId = DeviceId());
Action(const Action &other);
@ -41,7 +46,9 @@ public:
bool isValid() const;
ActionTypeId actionTypeId() const;
void setActionTypeId(const ActionTypeId &actionTypeId);
DeviceId deviceId() const;
void setDeviceId(const DeviceId &deviceId);
ParamList params() const;
void setParams(const ParamList &params);

View File

@ -123,6 +123,11 @@ ActionTypes::ActionTypes(const QList<ActionType> &other)
}
}
QVariant ActionTypes::get(int index)
{
return QVariant::fromValue(at(index));
}
ActionType ActionTypes::findByName(const QString &name)
{
foreach (const ActionType &actionType, *this) {

View File

@ -32,6 +32,13 @@
class LIBNYMEA_EXPORT ActionType
{
Q_GADGET
Q_PROPERTY(QUuid id READ id)
Q_PROPERTY(QString name READ name WRITE setName)
Q_PROPERTY(QString displayName READ displayName WRITE setDisplayName)
Q_PROPERTY(int index READ index WRITE setIndex)
Q_PROPERTY(ParamTypes paramTypes READ paramTypes WRITE setParamTypes)
public:
ActionType(const ActionTypeId &id = ActionTypeId());
@ -59,16 +66,21 @@ private:
int m_index;
ParamTypes m_paramTypes;
};
Q_DECLARE_METATYPE(ActionType)
QDebug operator<<(QDebug dbg, const ActionType &actionType);
class ActionTypes: public QList<ActionType>
{
Q_GADGET
Q_PROPERTY(int count READ count)
public:
ActionTypes() = default;
ActionTypes(const QList<ActionType> &other);
Q_INVOKABLE QVariant get(int index);
ActionType findByName(const QString &name);
ActionType findById(const ActionTypeId &id);
};
Q_DECLARE_METATYPE(ActionTypes)
#endif // ACTIONTYPE_H

View File

@ -33,6 +33,16 @@
class LIBNYMEA_EXPORT BrowserItem
{
Q_GADGET
Q_PROPERTY(QString id READ id)
Q_PROPERTY(QString displayName READ displayName)
Q_PROPERTY(QString description READ description)
Q_PROPERTY(BrowserIcon icon READ icon)
Q_PROPERTY(QString thumbnail READ thumbnail)
Q_PROPERTY(bool executable READ executable)
Q_PROPERTY(bool browsable READ browsable)
Q_PROPERTY(bool disabled READ disabled)
Q_PROPERTY(QList<ActionTypeId> actionTypeIds READ actionTypeIds)
public:
enum BrowserIcon {
BrowserIconNone,

View File

@ -38,6 +38,22 @@
class LIBNYMEA_EXPORT DeviceClass
{
Q_GADGET
Q_PROPERTY(QUuid id READ id)
Q_PROPERTY(QUuid vendorId READ vendorId)
Q_PROPERTY(QUuid pluginId READ pluginId)
Q_PROPERTY(QString name READ name)
Q_PROPERTY(QString displayName READ displayName)
Q_PROPERTY(QStringList interfaces READ interfaces)
Q_PROPERTY(bool browsable READ browsable)
Q_PROPERTY(SetupMethod setupMethod READ setupMethod)
Q_PROPERTY(CreateMethods createMethods READ createMethods)
Q_PROPERTY(StateTypes stateTypes READ stateTypes)
Q_PROPERTY(EventTypes eventTypes READ eventTypes)
Q_PROPERTY(ActionTypes actionTypes READ actionTypes)
Q_PROPERTY(ActionTypes browserItemActionTypes READ browserItemActionTypes)
Q_PROPERTY(ParamTypes paramTypes READ paramTypes)
Q_PROPERTY(ParamTypes settingsTypes READ settingsTypes)
Q_PROPERTY(ParamTypes discoveryParamTypes READ discoveryParamTypes)
public:
enum CreateMethod {
@ -47,6 +63,7 @@ public:
};
Q_ENUM(CreateMethod)
Q_DECLARE_FLAGS(CreateMethods, CreateMethod)
Q_FLAG(CreateMethods)
enum SetupMethod {
SetupMethodJustAdd,

View File

@ -108,7 +108,7 @@ Param Event::param(const ParamTypeId &paramTypeId) const
return param;
}
}
return Param(QString());
return Param(paramTypeId);
}
/*! Returns true if this event is autogenerated by a state change. */

View File

@ -34,6 +34,10 @@
class LIBNYMEA_EXPORT Event
{
Q_GADGET
Q_PROPERTY(QUuid eventTypeId READ eventTypeId)
Q_PROPERTY(QUuid deviceId READ deviceId)
Q_PROPERTY(ParamList params READ params)
public:
Event();
Event(const EventTypeId &eventTypeId, const DeviceId &deviceId, const ParamList &params = ParamList(), bool isStateChangeEvent = false);

View File

@ -33,6 +33,11 @@
#include "eventtype.h"
EventType::EventType()
{
}
/*! Constructs a EventType object with the given \a id. */
EventType::EventType(const EventTypeId &id):
m_id(id),
@ -123,6 +128,11 @@ EventTypes::EventTypes(const QList<EventType> &other)
}
}
QVariant EventTypes::get(int index)
{
return QVariant::fromValue(at(index));
}
EventType EventTypes::findByName(const QString &name)
{
foreach (const EventType &eventType, *this) {

View File

@ -32,7 +32,15 @@
class LIBNYMEA_EXPORT EventType
{
Q_GADGET
Q_PROPERTY(QUuid id READ id)
Q_PROPERTY(QString name READ name WRITE setName)
Q_PROPERTY(QString displayName READ displayName WRITE setDisplayName)
Q_PROPERTY(int index READ index)
Q_PROPERTY(ParamTypes paramTypes READ paramTypes WRITE setParamTypes)
public:
EventType();
EventType(const EventTypeId &id);
EventTypeId id() const;
@ -61,14 +69,19 @@ private:
int m_index;
QList<ParamType> m_paramTypes;
};
Q_DECLARE_METATYPE(EventType)
class EventTypes: public QList<EventType>
{
Q_GADGET
Q_PROPERTY(int count READ count)
public:
EventTypes() = default;
EventTypes(const QList<EventType> &other);
Q_INVOKABLE QVariant get(int index);
EventType findByName(const QString &name);
EventType findById(const EventTypeId &id);
};
Q_DECLARE_METATYPE(EventTypes)
#endif // TRIGGERTYPE_H

View File

@ -28,6 +28,8 @@
class MediaBrowserItem: public BrowserItem
{
Q_GADGET
Q_PROPERTY(MediaBrowserIcon mediaIcon READ mediaIcon)
public:
enum MediaBrowserIcon {
MediaBrowserIconNone = 1,

View File

@ -109,6 +109,11 @@ ParamList::ParamList(const QList<Param> &other): QList<Param>(other)
}
QVariant ParamList::get(int index)
{
return QVariant::fromValue(at(index));
}
/*! Returns true if this ParamList contains a Param with the given \a paramTypeId. */
bool ParamList::hasParam(const ParamTypeId &paramTypeId) const
{

View File

@ -32,6 +32,9 @@
class LIBNYMEA_EXPORT Param
{
Q_GADGET
Q_PROPERTY(QUuid paramTypeId READ paramTypeId)
Q_PROPERTY(QVariant value READ value WRITE setValue)
public:
Param(const ParamTypeId &paramTypeId = ParamTypeId(), const QVariant &value = QVariant());
@ -52,9 +55,12 @@ QDebug operator<<(QDebug dbg, const Param &param);
class LIBNYMEA_EXPORT ParamList: public QList<Param>
{
Q_GADGET
Q_PROPERTY(int count READ count)
public:
ParamList();
ParamList(const QList<Param> &other);
Q_INVOKABLE QVariant get(int index);
bool hasParam(const ParamTypeId &paramTypeId) const;
QVariant paramValue(const ParamTypeId &paramTypeId) const;
bool setParamValue(const ParamTypeId &paramTypeId, const QVariant &value);
@ -64,7 +70,7 @@ private:
QList<ParamTypeId> m_ids;
};
Q_DECLARE_METATYPE(ParamList)
QDebug operator<<(QDebug dbg, const ParamList &params);
#endif // PARAM_H

View File

@ -255,6 +255,11 @@ ParamTypes::ParamTypes(const QList<ParamType> &other): QList<ParamType>(other)
{
}
QVariant ParamTypes::get(int index)
{
return QVariant::fromValue(at(index));
}
ParamType ParamTypes::findByName(const QString &name)
{
foreach (const ParamType &paramType, *this) {

View File

@ -32,6 +32,20 @@
class LIBNYMEA_EXPORT ParamType
{
Q_GADGET
Q_PROPERTY(QUuid id READ id)
Q_PROPERTY(QString name READ name WRITE setName)
Q_PROPERTY(QString displayName READ displayName WRITE setDisplayName)
Q_PROPERTY(QVariant::Type type READ type WRITE setType)
Q_PROPERTY(int index READ index WRITE setIndex)
Q_PROPERTY(QVariant defaultValue READ defaultValue WRITE setDefaultValue USER true)
Q_PROPERTY(QVariant minValue READ minValue WRITE setMinValue USER true)
Q_PROPERTY(QVariant maxValue READ maxValue WRITE setMaxValue USER true)
Q_PROPERTY(QVariantList allowedValues READ allowedValues WRITE setAllowedValues USER true)
Q_PROPERTY(Types::InputType inputType READ inputType WRITE setInputType USER true)
Q_PROPERTY(Types::Unit unit READ unit WRITE setUnit USER true)
Q_PROPERTY(bool readOnly READ readOnly WRITE setReadOnly USER true)
public:
ParamType() = default;
ParamType(const ParamTypeId &id, const QString &name, const QVariant::Type type, const QVariant &defaultValue = QVariant());
@ -96,12 +110,17 @@ private:
class ParamTypes: public QList<ParamType>
{
Q_GADGET
Q_PROPERTY(int count READ count)
public:
ParamTypes() = default;
ParamTypes(const QList<ParamType> &other);
Q_INVOKABLE QVariant get(int index);
ParamType findByName(const QString &name);
ParamType findById(const ParamTypeId &id);
};
Q_DECLARE_METATYPE(QList<ParamType>)
Q_DECLARE_METATYPE(ParamTypes)
QDebug operator<<(QDebug dbg, const ParamType &paramType);
QDebug operator<<(QDebug dbg, const QList<ParamType> &paramTypes);

View File

@ -36,6 +36,11 @@
#include "state.h"
State::State()
{
}
/*! Constructs a State reflecting the \l{StateType} given by \a stateTypeId
* and associated with the \l{Device} given by \a deviceId */
State::State(const StateTypeId &stateTypeId, const DeviceId &deviceId):
@ -92,3 +97,18 @@ QDebug operator<<(QDebug dbg, const QList<State> &states)
return dbg.space();
}
States::States()
{
}
States::States(const QList<State> &other): QList<State>(other)
{
}
QVariant States::get(int index)
{
return QVariant::fromValue(at(index));
}

View File

@ -32,7 +32,12 @@
class LIBNYMEA_EXPORT State
{
Q_GADGET
Q_PROPERTY(QUuid stateTypeId READ stateTypeId)
Q_PROPERTY(QVariant value READ value)
public:
State();
State(const StateTypeId &stateTypeId, const DeviceId &deviceId);
StateId id() const;
@ -49,6 +54,18 @@ private:
DeviceId m_deviceId;
QVariant m_value;
};
Q_DECLARE_METATYPE(State)
class States: public QList<State>
{
Q_GADGET
Q_PROPERTY(int count READ count)
public:
States();
States(const QList<State> &other);
Q_INVOKABLE QVariant get(int index);
};
Q_DECLARE_METATYPE(States)
QDebug operator<<(QDebug dbg, const State &event);
QDebug operator<<(QDebug dbg, const QList<State> &events);

View File

@ -34,6 +34,11 @@
#include "statetype.h"
StateType::StateType()
{
}
/*! Constructs a StateType with the given \a id.
* When creating a \l{DevicePlugin} generate a new uuid for each StateType you define and
* hardcode it into the plugin json file. */
@ -193,6 +198,11 @@ StateTypes::StateTypes(const QList<StateType> &other)
}
}
QVariant StateTypes::get(int index)
{
return QVariant::fromValue(at(index));
}
StateType StateTypes::findByName(const QString &name)
{
foreach (const StateType &stateType, *this) {

View File

@ -32,7 +32,20 @@
class LIBNYMEA_EXPORT StateType
{
Q_GADGET
Q_PROPERTY(QUuid id READ id)
Q_PROPERTY(QString name READ name WRITE setName)
Q_PROPERTY(QString displayName READ displayName WRITE setDisplayName)
Q_PROPERTY(QVariant::Type type READ type WRITE setType)
Q_PROPERTY(int index READ index WRITE setIndex)
Q_PROPERTY(QVariant defaultValue READ defaultValue WRITE setDefaultValue)
Q_PROPERTY(Types::Unit unit READ unit WRITE setUnit USER true)
Q_PROPERTY(QVariant minValue READ minValue WRITE setMinValue USER true)
Q_PROPERTY(QVariant maxValue READ maxValue WRITE setMaxValue USER true)
Q_PROPERTY(QVariantList possibleValues READ possibleValues WRITE setPossibleValues USER true)
public:
StateType();
StateType(const StateTypeId &id);
StateTypeId id() const;
@ -83,14 +96,19 @@ private:
Types::Unit m_unit = Types::UnitNone;
bool m_cached = true;
};
Q_DECLARE_METATYPE(StateType)
class StateTypes: public QList<StateType>
{
Q_GADGET
Q_PROPERTY(int count READ count)
public:
StateTypes() = default;
StateTypes(const QList<StateType> &other);
Q_INVOKABLE QVariant get(int index);
StateType findByName(const QString &name);
StateType findById(const StateTypeId &id);
};
Q_DECLARE_METATYPE(StateTypes)
#endif // STATETYPE_H

View File

@ -32,6 +32,11 @@
class LIBNYMEA_EXPORT Vendor
{
Q_GADGET
Q_PROPERTY(QUuid id READ id WRITE setId)
Q_PROPERTY(QString name READ name WRITE setName)
Q_PROPERTY(QString displayName READ displayName WRITE setDisplayName)
public:
Vendor(const VendorId &id, const QString &name = QString());

View File

@ -32,7 +32,7 @@
#define DECLARE_TYPE_ID(type) class type##Id: public QUuid \
{ \
public: \
type##Id(const QString &uuid): QUuid(uuid) {} \
type##Id(const QUuid &uuid): QUuid(uuid) {} \
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()); } \

View File

@ -2,6 +2,10 @@
if [ -z $2 ]; then
echo "usage: $0 host actionTypeId"
else
(echo '{"id":1, "method":"Actions.GetActionType", "params":{"actionTypeId":"'$2'"}}'; sleep 1) | nc $1 2222
exit 1;
fi
cat << EOD | nc $1 2222
{"id":0, "method":"JSONRPC.Hello"}
{"id":1, "method":"Actions.GetActionType", "params":{"actionTypeId":"$2"}}
EOD

View File

@ -2,6 +2,11 @@
if [ -z $2 ]; then
echo "usage: $0 host deviceClassId"
else
(echo '{"id":1, "method":"Devices.GetActionTypes", "params":{"deviceClassId":"'$2'"}}'; sleep 1) | nc $1 2222
exit 1
fi
cat <<EOD | nc $1 2222
{"id":2, "method":"JSONRPC.Hello"}
{"id":1, "method":"Devices.GetActionTypes", "params":{"deviceClassId":"$2"}}
EOD

View File

@ -1,7 +1,21 @@
#!/bin/bash
if [ -z $1 ]; then
echo "usage: $0 host"
else
(echo '{"id":1, "token": "'$2'", "method":"Devices.GetConfiguredDevices"}'; sleep 1) | nc $1 2222
echo "usage: $0 host <token>"
exit 1
fi
if [ -z $2 ]; then
cat <<EOD | nc $1 2222
{"id":0, "method":"JSONRPC.Hello"}
{"id":1, "method":"Devices.GetConfiguredDevices"}
EOD
exit 0
fi
cat <<EOD | nc $1 2222
{"id":0, "method":"JSONRPC.Hello"}
{"id":1, "token": "$2", "method":"Devices.GetConfiguredDevices"}
EOD

11
tests/scripts/geteventtype.sh Executable file
View File

@ -0,0 +1,11 @@
#!/bin/bash
if [ -z $2 ]; then
echo "usage: $0 host actionTypeId"
exit 1;
fi
cat << EOD | nc $1 2222
{"id":0, "method":"JSONRPC.Hello"}
{"id":1, "method":"Events.GetEventType", "params":{"eventTypeId":"$2"}}
EOD

View File

@ -2,6 +2,10 @@
if [ -z $2 ]; then
echo "usage: $0 host deviceClassId"
else
(echo '{"id":1, "method":"Devices.GetEventTypes", "params":{"deviceClassId":"'$2'"}}'; sleep 1) | nc $1 2222
exit 1
fi
cat <<EOD | nc $1 2222
{"id":0, "method":"JSONRPC.Hello"}
{"id":1, "method":"Devices.GetEventTypes", "params":{"deviceClassId":"$2"}}
EOD

View File

@ -2,6 +2,11 @@
if [ -z $2 ]; then
echo "usage $0 host pluginid"
else
(echo '{"id":1, "method":"Devices.GetPluginConfiguration", "params":{"pluginId":"'$2'"}}'; sleep 1) | nc $1 2222
exit 1
fi
cat << EOD | nc $1 2222
{"id":0, "method": "JSONRPC.Hello"}
{"id":1, "method":"Devices.GetPluginConfiguration", "params":{"pluginId":"$2"}}
EOD

View File

@ -2,6 +2,10 @@
if [ -z $1 ]; then
echo "usage $0 host"
else
(echo '{"id":1, "method":"Devices.GetPlugins"}'; sleep 1) | nc $1 2222
exit 1
fi
cat << EOD | nc $1 2222
{"id":0, "method": "JSONRPC.Hello"}
{"id":1, "method": "Devices.GetPlugins"}
EOD

View File

@ -1,9 +1,21 @@
#!/bin/bash
if [ -z $1 ]; then
echo "usage $0 host"
elif [ -z $2 ]; then
(echo '{"id":1, "method":"Devices.GetSupportedDevices"}'; sleep 1) | nc $1 2222
else
(echo '{"id":1, "method":"Devices.GetSupportedDevices", "params":{"vendorId":"'$2'"}}'; sleep 1) | nc $1 2222
echo "usage $0 host [vendorId]"
exit 1;
fi
if [ -z $2 ]; then
cat << EOD | nc $1 2222
{"id":0, "method": "JSONRPC.Hello"}
{"id":1, "method": "Devices.GetSupportedDevices"}
EOD
else
cat << EOD | nc $1 2222
{"id":0, "method": "JSONRPC.Hello"}
{"id":1, "method": "Devices.GetSupportedDevices", "params":{"vendorId":"$2"}}
EOD
fi

11
tests/scripts/token.sh Executable file
View File

@ -0,0 +1,11 @@
#!/bin/bash
if [ -z $1 ]; then
echo "usage: $0 host"
exit 1;
fi
cat << EOD | nc $1 2222
{"id":0, "method":"JSONRPC.Hello"}
{"id":1, "method":"JSONRPC.Tokens"}
EOD