mirror of https://github.com/nymea/nymea.git
Add support for interface based script events and actions
parent
a0add78af0
commit
79dd00cb57
|
|
@ -33,6 +33,8 @@ HEADERS += nymeacore.h \
|
||||||
scriptengine/scriptalarm.h \
|
scriptengine/scriptalarm.h \
|
||||||
scriptengine/scriptengine.h \
|
scriptengine/scriptengine.h \
|
||||||
scriptengine/scriptevent.h \
|
scriptengine/scriptevent.h \
|
||||||
|
scriptengine/scriptinterfaceaction.h \
|
||||||
|
scriptengine/scriptinterfaceevent.h \
|
||||||
scriptengine/scriptstate.h \
|
scriptengine/scriptstate.h \
|
||||||
transportinterface.h \
|
transportinterface.h \
|
||||||
nymeaconfiguration.h \
|
nymeaconfiguration.h \
|
||||||
|
|
@ -112,6 +114,8 @@ SOURCES += nymeacore.cpp \
|
||||||
scriptengine/scriptalarm.cpp \
|
scriptengine/scriptalarm.cpp \
|
||||||
scriptengine/scriptengine.cpp \
|
scriptengine/scriptengine.cpp \
|
||||||
scriptengine/scriptevent.cpp \
|
scriptengine/scriptevent.cpp \
|
||||||
|
scriptengine/scriptinterfaceaction.cpp \
|
||||||
|
scriptengine/scriptinterfaceevent.cpp \
|
||||||
scriptengine/scriptstate.cpp \
|
scriptengine/scriptstate.cpp \
|
||||||
transportinterface.cpp \
|
transportinterface.cpp \
|
||||||
nymeaconfiguration.cpp \
|
nymeaconfiguration.cpp \
|
||||||
|
|
|
||||||
|
|
@ -68,6 +68,19 @@ void ScriptAction::setThingId(const QString &thingId)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QString ScriptAction::interfaceName() const
|
||||||
|
{
|
||||||
|
return m_interfaceName;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ScriptAction::setInterfaceName(const QString &interfaceName)
|
||||||
|
{
|
||||||
|
if (m_interfaceName != interfaceName) {
|
||||||
|
m_interfaceName = interfaceName;
|
||||||
|
emit interfaceNameChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
QString ScriptAction::actionTypeId() const
|
QString ScriptAction::actionTypeId() const
|
||||||
{
|
{
|
||||||
return m_actionTypeId;
|
return m_actionTypeId;
|
||||||
|
|
@ -96,11 +109,24 @@ void ScriptAction::setActionName(const QString &actionName)
|
||||||
|
|
||||||
void ScriptAction::execute(const QVariantMap ¶ms)
|
void ScriptAction::execute(const QVariantMap ¶ms)
|
||||||
{
|
{
|
||||||
|
Things things;
|
||||||
|
if (m_thingId.isEmpty() && !m_interfaceName.isEmpty()) {
|
||||||
|
foreach (Thing *thing, m_thingManager->configuredThings()) {
|
||||||
|
if (thing->thingClass().interfaces().contains(m_interfaceName)) {
|
||||||
|
things.append(thing);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Thing *thing = m_thingManager->configuredThings().findById(ThingId(m_thingId));
|
Thing *thing = m_thingManager->configuredThings().findById(ThingId(m_thingId));
|
||||||
if (!thing) {
|
if (thing && !things.contains(thing)) {
|
||||||
qCWarning(dcScriptEngine) << "No thing with id" << m_thingId;
|
things.append(thing);
|
||||||
|
}
|
||||||
|
if (things.isEmpty()) {
|
||||||
|
qCWarning(dcScriptEngine) << "No things matching by id" << m_thingId << "and interface" << m_interfaceName;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
foreach (Thing *thing, things) {
|
||||||
ActionType actionType;
|
ActionType actionType;
|
||||||
if (!ActionTypeId(m_actionTypeId).isNull()) {
|
if (!ActionTypeId(m_actionTypeId).isNull()) {
|
||||||
actionType = thing->thingClass().actionTypes().findById(ActionTypeId(m_actionTypeId));
|
actionType = thing->thingClass().actionTypes().findById(ActionTypeId(m_actionTypeId));
|
||||||
|
|
@ -108,10 +134,10 @@ void ScriptAction::execute(const QVariantMap ¶ms)
|
||||||
actionType = thing->thingClass().actionTypes().findByName(m_actionName);
|
actionType = thing->thingClass().actionTypes().findByName(m_actionName);
|
||||||
}
|
}
|
||||||
if (actionType.id().isNull()) {
|
if (actionType.id().isNull()) {
|
||||||
qCWarning(dcScriptEngine()) << "Either a valid actionTypeId or actionName is required";
|
qCWarning(dcScriptEngine()) << "Thing" << thing->name() << "does not have actionTypeId" << m_actionTypeId << "or actionName" << m_actionName;
|
||||||
return;
|
continue;
|
||||||
}
|
}
|
||||||
Action action(actionType.id(), ThingId(m_thingId), Action::TriggeredByScript);
|
Action action(actionType.id(), thing->id(), Action::TriggeredByScript);
|
||||||
ParamList paramList;
|
ParamList paramList;
|
||||||
foreach (const QString ¶mNameOrId, params.keys()) {
|
foreach (const QString ¶mNameOrId, params.keys()) {
|
||||||
ParamType paramType;
|
ParamType paramType;
|
||||||
|
|
@ -127,7 +153,9 @@ void ScriptAction::execute(const QVariantMap ¶ms)
|
||||||
paramList << Param(paramType.id(), params.value(paramNameOrId));
|
paramList << Param(paramType.id(), params.value(paramNameOrId));
|
||||||
}
|
}
|
||||||
action.setParams(paramList);
|
action.setParams(paramList);
|
||||||
|
qCDebug(dcScriptEngine()) << "Executing action:" << action.thingId() << action.actionTypeId() << action.params();
|
||||||
m_thingManager->executeAction(action);
|
m_thingManager->executeAction(action);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -43,6 +43,7 @@ class ScriptAction : public QObject, public QQmlParserStatus
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
Q_INTERFACES(QQmlParserStatus)
|
Q_INTERFACES(QQmlParserStatus)
|
||||||
Q_PROPERTY(QString thingId READ thingId WRITE setThingId NOTIFY thingIdChanged)
|
Q_PROPERTY(QString thingId READ thingId WRITE setThingId NOTIFY thingIdChanged)
|
||||||
|
Q_PROPERTY(QString interfaceName READ interfaceName WRITE setInterfaceName NOTIFY interfaceNameChanged)
|
||||||
Q_PROPERTY(QString deviceId READ thingId WRITE setThingId NOTIFY thingIdChanged) // DEPRECATED
|
Q_PROPERTY(QString deviceId READ thingId WRITE setThingId NOTIFY thingIdChanged) // DEPRECATED
|
||||||
Q_PROPERTY(QString actionTypeId READ actionTypeId WRITE setActionTypeId NOTIFY actionTypeIdChanged)
|
Q_PROPERTY(QString actionTypeId READ actionTypeId WRITE setActionTypeId NOTIFY actionTypeIdChanged)
|
||||||
Q_PROPERTY(QString actionName READ actionName WRITE setActionName NOTIFY actionNameChanged)
|
Q_PROPERTY(QString actionName READ actionName WRITE setActionName NOTIFY actionNameChanged)
|
||||||
|
|
@ -54,6 +55,9 @@ public:
|
||||||
QString thingId() const;
|
QString thingId() const;
|
||||||
void setThingId(const QString &thingId);
|
void setThingId(const QString &thingId);
|
||||||
|
|
||||||
|
QString interfaceName() const;
|
||||||
|
void setInterfaceName(const QString &interfaceName);
|
||||||
|
|
||||||
QString actionTypeId() const;
|
QString actionTypeId() const;
|
||||||
void setActionTypeId(const QString &actionTypeId);
|
void setActionTypeId(const QString &actionTypeId);
|
||||||
|
|
||||||
|
|
@ -65,12 +69,14 @@ public slots:
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void thingIdChanged();
|
void thingIdChanged();
|
||||||
|
void interfaceNameChanged();
|
||||||
void actionTypeIdChanged();
|
void actionTypeIdChanged();
|
||||||
void actionNameChanged();
|
void actionNameChanged();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ThingManager *m_thingManager = nullptr;
|
ThingManager *m_thingManager = nullptr;
|
||||||
QString m_thingId;
|
QString m_thingId;
|
||||||
|
QString m_interfaceName;
|
||||||
QString m_actionTypeId;
|
QString m_actionTypeId;
|
||||||
QString m_actionName;
|
QString m_actionName;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -35,6 +35,8 @@
|
||||||
#include "scriptevent.h"
|
#include "scriptevent.h"
|
||||||
#include "scriptstate.h"
|
#include "scriptstate.h"
|
||||||
#include "scriptalarm.h"
|
#include "scriptalarm.h"
|
||||||
|
#include "scriptinterfaceaction.h"
|
||||||
|
#include "scriptinterfaceevent.h"
|
||||||
|
|
||||||
#include "nymeasettings.h"
|
#include "nymeasettings.h"
|
||||||
|
|
||||||
|
|
@ -63,6 +65,8 @@ ScriptEngine::ScriptEngine(ThingManager *deviceManager, QObject *parent) : QObje
|
||||||
qmlRegisterType<ScriptEvent>("nymea", 1, 0, "ThingEvent");
|
qmlRegisterType<ScriptEvent>("nymea", 1, 0, "ThingEvent");
|
||||||
qmlRegisterType<ScriptAction>("nymea", 1, 0, "ThingAction");
|
qmlRegisterType<ScriptAction>("nymea", 1, 0, "ThingAction");
|
||||||
qmlRegisterType<ScriptState>("nymea", 1, 0, "ThingState");
|
qmlRegisterType<ScriptState>("nymea", 1, 0, "ThingState");
|
||||||
|
qmlRegisterType<ScriptInterfaceAction>("nymea", 1, 0, "InterfaceAction");
|
||||||
|
qmlRegisterType<ScriptInterfaceEvent>("nymea", 1, 0, "InterfaceEvent");
|
||||||
qmlRegisterType<ScriptAlarm>("nymea", 1, 0, "Alarm");
|
qmlRegisterType<ScriptAlarm>("nymea", 1, 0, "Alarm");
|
||||||
|
|
||||||
m_engine = new QQmlEngine(this);
|
m_engine = new QQmlEngine(this);
|
||||||
|
|
|
||||||
|
|
@ -28,8 +28,8 @@
|
||||||
*
|
*
|
||||||
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||||
|
|
||||||
#ifndef EVENTLISTENER_H
|
#ifndef SCRIPTEVENT_H
|
||||||
#define EVENTLISTENER_H
|
#define SCRIPTEVENT_H
|
||||||
|
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
#include <QUuid>
|
#include <QUuid>
|
||||||
|
|
@ -72,7 +72,6 @@ signals:
|
||||||
void eventTypeIdChanged();
|
void eventTypeIdChanged();
|
||||||
void eventNameChanged();
|
void eventNameChanged();
|
||||||
|
|
||||||
// void triggered(ScriptParams *params);
|
|
||||||
void triggered(const QVariantMap ¶ms);
|
void triggered(const QVariantMap ¶ms);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
@ -85,4 +84,4 @@ private:
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // EVENTLISTENER_H
|
#endif // SCRIPTEVENT_H
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,126 @@
|
||||||
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||||
|
*
|
||||||
|
* Copyright 2013 - 2020, nymea GmbH
|
||||||
|
* Contact: contact@nymea.io
|
||||||
|
*
|
||||||
|
* This file is part of nymea.
|
||||||
|
* This project including source code and documentation is protected by
|
||||||
|
* copyright law, and remains the property of nymea GmbH. All rights, including
|
||||||
|
* reproduction, publication, editing and translation, are reserved. The use of
|
||||||
|
* this project is subject to the terms of a license agreement to be concluded
|
||||||
|
* with nymea GmbH in accordance with the terms of use of nymea GmbH, available
|
||||||
|
* under https://nymea.io/license
|
||||||
|
*
|
||||||
|
* GNU General Public License Usage
|
||||||
|
* Alternatively, this project may be redistributed and/or modified under the
|
||||||
|
* terms of the GNU General Public License as published by the Free Software
|
||||||
|
* Foundation, GNU version 3. This project is distributed in the hope that it
|
||||||
|
* will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
|
||||||
|
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
|
||||||
|
* Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along with
|
||||||
|
* this project. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
* For any further details and any questions please contact us under
|
||||||
|
* contact@nymea.io or see our FAQ/Licensing Information on
|
||||||
|
* https://nymea.io/license/faq
|
||||||
|
*
|
||||||
|
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||||
|
|
||||||
|
#include "scriptinterfaceaction.h"
|
||||||
|
|
||||||
|
#include "integrations/thingmanager.h"
|
||||||
|
#include "types/action.h"
|
||||||
|
|
||||||
|
#include <QQmlEngine>
|
||||||
|
#include <qqml.h>
|
||||||
|
|
||||||
|
#include "loggingcategories.h"
|
||||||
|
|
||||||
|
namespace nymeaserver {
|
||||||
|
|
||||||
|
ScriptInterfaceAction::ScriptInterfaceAction(QObject *parent) : QObject(parent)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void ScriptInterfaceAction::classBegin()
|
||||||
|
{
|
||||||
|
m_thingManager = reinterpret_cast<ThingManager*>(qmlEngine(this)->property("thingManager").toULongLong());
|
||||||
|
}
|
||||||
|
|
||||||
|
void ScriptInterfaceAction::componentComplete()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
QString ScriptInterfaceAction::interfaceName() const
|
||||||
|
{
|
||||||
|
return m_interfaceName;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ScriptInterfaceAction::setInterfaceName(const QString &interfaceName)
|
||||||
|
{
|
||||||
|
if (m_interfaceName != interfaceName) {
|
||||||
|
m_interfaceName = interfaceName;
|
||||||
|
emit interfaceNameChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QString ScriptInterfaceAction::actionName() const
|
||||||
|
{
|
||||||
|
return m_actionName;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ScriptInterfaceAction::setActionName(const QString &actionName)
|
||||||
|
{
|
||||||
|
if (m_actionName != actionName) {
|
||||||
|
m_actionName = actionName;
|
||||||
|
emit actionNameChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ScriptInterfaceAction::execute(const QVariantMap ¶ms)
|
||||||
|
{
|
||||||
|
Things things;
|
||||||
|
if (!m_interfaceName.isEmpty()) {
|
||||||
|
foreach (Thing *thing, m_thingManager->configuredThings()) {
|
||||||
|
if (thing->thingClass().interfaces().contains(m_interfaceName)) {
|
||||||
|
things.append(thing);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (things.isEmpty()) {
|
||||||
|
qCWarning(dcScriptEngine) << "No things matching by interface" << m_interfaceName;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (Thing *thing, things) {
|
||||||
|
ActionType actionType = thing->thingClass().actionTypes().findByName(m_actionName);
|
||||||
|
if (actionType.id().isNull()) {
|
||||||
|
qCWarning(dcScriptEngine()) << "Thing" << thing->name() << "does not have action" << m_actionName;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
Action action(actionType.id(), thing->id(), Action::TriggeredByScript);
|
||||||
|
ParamList paramList;
|
||||||
|
foreach (const QString ¶mNameOrId, params.keys()) {
|
||||||
|
ParamType paramType;
|
||||||
|
if (!ParamTypeId(paramNameOrId).isNull()) {
|
||||||
|
paramType = actionType.paramTypes().findById(ParamTypeId(paramNameOrId));
|
||||||
|
} else {
|
||||||
|
paramType = actionType.paramTypes().findByName(paramNameOrId);
|
||||||
|
}
|
||||||
|
if (paramType.id().isNull()) {
|
||||||
|
qCWarning(dcScriptEngine()) << "Invalid param id or name";
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
paramList << Param(paramType.id(), params.value(paramNameOrId));
|
||||||
|
}
|
||||||
|
action.setParams(paramList);
|
||||||
|
qCDebug(dcScriptEngine()) << "Executing action:" << action.thingId() << action.actionTypeId() << action.params();
|
||||||
|
m_thingManager->executeAction(action);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,73 @@
|
||||||
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||||
|
*
|
||||||
|
* Copyright 2013 - 2020, nymea GmbH
|
||||||
|
* Contact: contact@nymea.io
|
||||||
|
*
|
||||||
|
* This file is part of nymea.
|
||||||
|
* This project including source code and documentation is protected by
|
||||||
|
* copyright law, and remains the property of nymea GmbH. All rights, including
|
||||||
|
* reproduction, publication, editing and translation, are reserved. The use of
|
||||||
|
* this project is subject to the terms of a license agreement to be concluded
|
||||||
|
* with nymea GmbH in accordance with the terms of use of nymea GmbH, available
|
||||||
|
* under https://nymea.io/license
|
||||||
|
*
|
||||||
|
* GNU General Public License Usage
|
||||||
|
* Alternatively, this project may be redistributed and/or modified under the
|
||||||
|
* terms of the GNU General Public License as published by the Free Software
|
||||||
|
* Foundation, GNU version 3. This project is distributed in the hope that it
|
||||||
|
* will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
|
||||||
|
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
|
||||||
|
* Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along with
|
||||||
|
* this project. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
* For any further details and any questions please contact us under
|
||||||
|
* contact@nymea.io or see our FAQ/Licensing Information on
|
||||||
|
* https://nymea.io/license/faq
|
||||||
|
*
|
||||||
|
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||||
|
|
||||||
|
#ifndef SCRIPTINTERFACEACTION_H
|
||||||
|
#define SCRIPTINTERFACEACTION_H
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
#include <QQmlParserStatus>
|
||||||
|
|
||||||
|
class ThingManager;
|
||||||
|
|
||||||
|
namespace nymeaserver {
|
||||||
|
|
||||||
|
class ScriptInterfaceAction : public QObject, public QQmlParserStatus
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
Q_INTERFACES(QQmlParserStatus)
|
||||||
|
Q_PROPERTY(QString interfaceName READ interfaceName WRITE setInterfaceName NOTIFY interfaceNameChanged)
|
||||||
|
Q_PROPERTY(QString actionName READ actionName WRITE setActionName NOTIFY actionNameChanged)
|
||||||
|
public:
|
||||||
|
explicit ScriptInterfaceAction(QObject *parent = nullptr);
|
||||||
|
void classBegin() override;
|
||||||
|
void componentComplete() override;
|
||||||
|
|
||||||
|
QString interfaceName() const;
|
||||||
|
void setInterfaceName(const QString &interfaceName);
|
||||||
|
|
||||||
|
QString actionName() const;
|
||||||
|
void setActionName(const QString &actionName);
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
void execute(const QVariantMap ¶ms);
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void interfaceNameChanged();
|
||||||
|
void actionNameChanged();
|
||||||
|
|
||||||
|
public:
|
||||||
|
ThingManager *m_thingManager = nullptr;
|
||||||
|
QString m_interfaceName;
|
||||||
|
QString m_actionName;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // SCRIPTINTERFACEACTION_H
|
||||||
|
|
@ -0,0 +1,103 @@
|
||||||
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||||
|
*
|
||||||
|
* Copyright 2013 - 2020, nymea GmbH
|
||||||
|
* Contact: contact@nymea.io
|
||||||
|
*
|
||||||
|
* This file is part of nymea.
|
||||||
|
* This project including source code and documentation is protected by
|
||||||
|
* copyright law, and remains the property of nymea GmbH. All rights, including
|
||||||
|
* reproduction, publication, editing and translation, are reserved. The use of
|
||||||
|
* this project is subject to the terms of a license agreement to be concluded
|
||||||
|
* with nymea GmbH in accordance with the terms of use of nymea GmbH, available
|
||||||
|
* under https://nymea.io/license
|
||||||
|
*
|
||||||
|
* GNU General Public License Usage
|
||||||
|
* Alternatively, this project may be redistributed and/or modified under the
|
||||||
|
* terms of the GNU General Public License as published by the Free Software
|
||||||
|
* Foundation, GNU version 3. This project is distributed in the hope that it
|
||||||
|
* will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
|
||||||
|
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
|
||||||
|
* Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along with
|
||||||
|
* this project. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
* For any further details and any questions please contact us under
|
||||||
|
* contact@nymea.io or see our FAQ/Licensing Information on
|
||||||
|
* https://nymea.io/license/faq
|
||||||
|
*
|
||||||
|
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||||
|
|
||||||
|
#include "scriptinterfaceevent.h"
|
||||||
|
|
||||||
|
#include <qqml.h>
|
||||||
|
#include <QQmlEngine>
|
||||||
|
#include <QJsonDocument>
|
||||||
|
|
||||||
|
namespace nymeaserver {
|
||||||
|
|
||||||
|
ScriptInterfaceEvent::ScriptInterfaceEvent(QObject *parent) : QObject(parent)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void ScriptInterfaceEvent::classBegin()
|
||||||
|
{
|
||||||
|
m_thingManager = reinterpret_cast<ThingManager*>(qmlEngine(this)->property("thingManager").toULongLong());
|
||||||
|
connect(m_thingManager, &ThingManager::eventTriggered, this, &ScriptInterfaceEvent::onEventTriggered);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ScriptInterfaceEvent::componentComplete()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
QString ScriptInterfaceEvent::interfaceName() const
|
||||||
|
{
|
||||||
|
return m_interfaceName;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ScriptInterfaceEvent::setInterfaceName(const QString &interfaceName)
|
||||||
|
{
|
||||||
|
if (m_interfaceName != interfaceName) {
|
||||||
|
m_interfaceName = interfaceName;
|
||||||
|
emit interfaceNameChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QString ScriptInterfaceEvent::eventName() const
|
||||||
|
{
|
||||||
|
return m_eventName;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ScriptInterfaceEvent::setEventName(const QString &eventName)
|
||||||
|
{
|
||||||
|
if (m_eventName != eventName) {
|
||||||
|
m_eventName = eventName;
|
||||||
|
emit eventNameChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ScriptInterfaceEvent::onEventTriggered(const Event &event)
|
||||||
|
{
|
||||||
|
Thing *thing = m_thingManager->findConfiguredThing(event.thingId());
|
||||||
|
if (!thing->thingClass().interfaces().contains(m_interfaceName)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!m_eventName.isEmpty() && thing->thingClass().eventTypes().findByName(m_eventName).id() != event.eventTypeId()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariantMap params;
|
||||||
|
foreach (const Param ¶m, event.params()) {
|
||||||
|
params.insert(param.paramTypeId().toString().remove(QRegExp("[{}]")), param.value().toByteArray());
|
||||||
|
QString paramName = thing->thingClass().eventTypes().findById(event.eventTypeId()).paramTypes().findById(param.paramTypeId()).name();
|
||||||
|
params.insert(paramName, param.value().toByteArray());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Note: Explicitly convert the params to a Json document because auto-casting from QVariantMap to the JS engine might drop some values.
|
||||||
|
emit triggered(event.thingId().toString().remove(QRegExp("[{}]")), QJsonDocument::fromVariant(params).toVariant().toMap());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -0,0 +1,80 @@
|
||||||
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||||
|
*
|
||||||
|
* Copyright 2013 - 2020, nymea GmbH
|
||||||
|
* Contact: contact@nymea.io
|
||||||
|
*
|
||||||
|
* This file is part of nymea.
|
||||||
|
* This project including source code and documentation is protected by
|
||||||
|
* copyright law, and remains the property of nymea GmbH. All rights, including
|
||||||
|
* reproduction, publication, editing and translation, are reserved. The use of
|
||||||
|
* this project is subject to the terms of a license agreement to be concluded
|
||||||
|
* with nymea GmbH in accordance with the terms of use of nymea GmbH, available
|
||||||
|
* under https://nymea.io/license
|
||||||
|
*
|
||||||
|
* GNU General Public License Usage
|
||||||
|
* Alternatively, this project may be redistributed and/or modified under the
|
||||||
|
* terms of the GNU General Public License as published by the Free Software
|
||||||
|
* Foundation, GNU version 3. This project is distributed in the hope that it
|
||||||
|
* will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
|
||||||
|
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
|
||||||
|
* Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along with
|
||||||
|
* this project. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
* For any further details and any questions please contact us under
|
||||||
|
* contact@nymea.io or see our FAQ/Licensing Information on
|
||||||
|
* https://nymea.io/license/faq
|
||||||
|
*
|
||||||
|
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||||
|
|
||||||
|
#ifndef SCRIPTINTERFACEEVENT_H
|
||||||
|
#define SCRIPTINTERFACEEVENT_H
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
#include <QUuid>
|
||||||
|
#include <QQmlParserStatus>
|
||||||
|
|
||||||
|
#include "types/event.h"
|
||||||
|
#include "integrations/thingmanager.h"
|
||||||
|
|
||||||
|
namespace nymeaserver {
|
||||||
|
|
||||||
|
class ScriptParams;
|
||||||
|
|
||||||
|
class ScriptInterfaceEvent: public QObject, public QQmlParserStatus
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
Q_INTERFACES(QQmlParserStatus)
|
||||||
|
Q_PROPERTY(QString interfaceName READ interfaceName WRITE setInterfaceName NOTIFY interfaceNameChanged)
|
||||||
|
Q_PROPERTY(QString eventName READ eventName WRITE setEventName NOTIFY eventNameChanged)
|
||||||
|
public:
|
||||||
|
ScriptInterfaceEvent(QObject *parent = nullptr);
|
||||||
|
void classBegin() override;
|
||||||
|
void componentComplete() override;
|
||||||
|
|
||||||
|
QString interfaceName() const;
|
||||||
|
void setInterfaceName(const QString &interfaceName);
|
||||||
|
|
||||||
|
QString eventName() const;
|
||||||
|
void setEventName(const QString &eventName);
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void onEventTriggered(const Event &event);
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void interfaceNameChanged();
|
||||||
|
void eventNameChanged();
|
||||||
|
|
||||||
|
void triggered(const QString &thingId, const QVariantMap ¶ms);
|
||||||
|
|
||||||
|
private:
|
||||||
|
ThingManager *m_thingManager = nullptr;
|
||||||
|
|
||||||
|
QString m_interfaceName;
|
||||||
|
QString m_eventName;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // SCRIPTINTERFACEEVENT_H
|
||||||
|
|
@ -70,6 +70,9 @@ private slots:
|
||||||
|
|
||||||
void testScriptAlarm_data();
|
void testScriptAlarm_data();
|
||||||
void testScriptAlarm();
|
void testScriptAlarm();
|
||||||
|
|
||||||
|
void testInterfaceEvent();
|
||||||
|
void testInterfaceAction();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -383,6 +386,80 @@ void TestScripts::testScriptAlarm()
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TestScripts::testInterfaceEvent()
|
||||||
|
{
|
||||||
|
QString script = QString("import QtQuick 2.0\n"
|
||||||
|
"import nymea 1.0\n"
|
||||||
|
"Item {\n"
|
||||||
|
" InterfaceEvent {\n"
|
||||||
|
" interfaceName: \"%1\"\n"
|
||||||
|
" eventName: \"%2\"\n"
|
||||||
|
" onTriggered: {\n"
|
||||||
|
" TestHelper.logEvent(thingId, eventName, params);\n"
|
||||||
|
" }\n"
|
||||||
|
" }\n"
|
||||||
|
"}\n").arg("power").arg("power");
|
||||||
|
|
||||||
|
qCDebug(dcTests()) << "Adding script:\n" << qUtf8Printable(script);
|
||||||
|
ScriptEngine::AddScriptReply reply = NymeaCore::instance()->scriptEngine()->addScript("TestEvent", script.toUtf8());
|
||||||
|
QCOMPARE(reply.scriptError, ScriptEngine::ScriptErrorNoError);
|
||||||
|
|
||||||
|
QSignalSpy spy(TestHelper::instance(), &TestHelper::eventLogged);
|
||||||
|
|
||||||
|
// Generate event by setting state value of powerState
|
||||||
|
Action action(mockPowerActionTypeId, m_mockThingId);
|
||||||
|
action.setParams(ParamList() << Param(mockPowerActionPowerParamTypeId, true));
|
||||||
|
NymeaCore::instance()->thingManager()->executeAction(action);
|
||||||
|
|
||||||
|
spy.wait(1);
|
||||||
|
|
||||||
|
QCOMPARE(spy.count(), 1);
|
||||||
|
QCOMPARE(spy.first().at(0).value<ThingId>(), m_mockThingId);
|
||||||
|
QCOMPARE(spy.first().at(1).toString(), QString("power"));
|
||||||
|
QVariantMap expectedParams;
|
||||||
|
expectedParams.insert(mockPowerEventTypeId.toString().remove(QRegExp("[{}]")), true);
|
||||||
|
expectedParams.insert("power", true);
|
||||||
|
QCOMPARE(spy.first().at(2).toMap(), expectedParams);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void TestScripts::testInterfaceAction()
|
||||||
|
{
|
||||||
|
QString script = QString("import QtQuick 2.0\n"
|
||||||
|
"import nymea 1.0\n"
|
||||||
|
"Item {\n"
|
||||||
|
" InterfaceAction {\n"
|
||||||
|
" id: interfaceAction\n"
|
||||||
|
" interfaceName: \"%1\"\n"
|
||||||
|
" actionName: \"%2\"\n"
|
||||||
|
" }\n"
|
||||||
|
" Connections {\n"
|
||||||
|
" target: TestHelper\n"
|
||||||
|
" onExecuteAction: {\n"
|
||||||
|
" interfaceAction.execute(params)\n"
|
||||||
|
" }\n"
|
||||||
|
" }\n"
|
||||||
|
"}\n").arg("power").arg("power");
|
||||||
|
|
||||||
|
qCDebug(dcTests()) << "Adding script:\n" << qUtf8Printable(script);
|
||||||
|
ScriptEngine::AddScriptReply reply = NymeaCore::instance()->scriptEngine()->addScript("TestInterfaceAction", script.toUtf8());
|
||||||
|
QCOMPARE(reply.scriptError, ScriptEngine::ScriptErrorNoError);
|
||||||
|
|
||||||
|
QSignalSpy spy(NymeaCore::instance()->thingManager(), &ThingManager::thingStateChanged);
|
||||||
|
|
||||||
|
QVariantMap params;
|
||||||
|
params.insert("power", true);
|
||||||
|
TestHelper::instance()->executeAction(params);
|
||||||
|
|
||||||
|
spy.wait(1);
|
||||||
|
|
||||||
|
QCOMPARE(spy.count(), 1);
|
||||||
|
QCOMPARE(spy.first().at(0).value<Thing*>()->id(), m_mockThingId);
|
||||||
|
QCOMPARE(spy.first().at(1).value<StateTypeId>(), mockPowerStateTypeId);
|
||||||
|
QCOMPARE(spy.first().at(2).toBool(), true);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#include "testscripts.moc"
|
#include "testscripts.moc"
|
||||||
QTEST_MAIN(TestScripts)
|
QTEST_MAIN(TestScripts)
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue