Add support for connection to actionExecuted in scripts
This commit is contained in:
parent
1e75df2782
commit
0c09e07112
@ -37,6 +37,7 @@
|
||||
#include <QQmlEngine>
|
||||
#include <qqml.h>
|
||||
#include <QQmlContext>
|
||||
#include <QJsonDocument>
|
||||
|
||||
#include <QLoggingCategory>
|
||||
Q_DECLARE_LOGGING_CATEGORY(dcScriptEngine)
|
||||
@ -56,6 +57,34 @@ void ScriptAction::classBegin()
|
||||
m_scriptId = qmlEngine(this)->contextForObject(this)->contextProperty("scriptId").toUuid();
|
||||
m_logger = qmlEngine(this)->contextForObject(this)->contextProperty("logger").value<Logger*>();
|
||||
|
||||
connect(m_thingManager, &ThingManager::actionExecuted, this, [=](const Action &action, Thing::ThingError status){
|
||||
if (ThingId(m_thingId) != action.thingId()) {
|
||||
return;
|
||||
}
|
||||
|
||||
Thing *thing = m_thingManager->findConfiguredThing(ThingId(m_thingId));
|
||||
if (!thing) {
|
||||
return;
|
||||
}
|
||||
|
||||
ActionTypeId ourActionTypeId = ActionTypeId(m_actionTypeId);
|
||||
if (ourActionTypeId.isNull()) {
|
||||
ourActionTypeId = thing->thingClass().actionTypes().findByName(m_actionName).id();
|
||||
}
|
||||
if (ourActionTypeId.isNull() || action.actionTypeId() != ourActionTypeId) {
|
||||
return;
|
||||
}
|
||||
|
||||
QVariantMap params;
|
||||
foreach (const Param ¶m, action.params()) {
|
||||
params.insert(param.paramTypeId().toString().remove(QRegExp("[{}]")), param.value().toByteArray());
|
||||
QString paramName = thing->thingClass().actionTypes().findById(action.actionTypeId()).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 executed(QJsonDocument::fromVariant(params).toVariant().toMap(), status, action.triggeredBy());
|
||||
});
|
||||
}
|
||||
|
||||
void ScriptAction::componentComplete()
|
||||
|
||||
@ -36,6 +36,9 @@
|
||||
#include <QVariantMap>
|
||||
#include <QUuid>
|
||||
|
||||
#include "integrations/thing.h"
|
||||
#include "types/action.h"
|
||||
|
||||
class Logger;
|
||||
class ThingManager;
|
||||
|
||||
@ -77,6 +80,8 @@ signals:
|
||||
void actionTypeIdChanged();
|
||||
void actionNameChanged();
|
||||
|
||||
void executed(const QVariantMap ¶ms, Thing::ThingError status, Action::TriggeredBy triggeredBy);
|
||||
|
||||
public:
|
||||
ThingManager *m_thingManager = nullptr;
|
||||
Logger *m_logger = nullptr;
|
||||
|
||||
@ -40,6 +40,7 @@
|
||||
#include "scriptinterfaceevent.h"
|
||||
#include "scriptthing.h"
|
||||
#include "scriptthings.h"
|
||||
#include "types/action.h"
|
||||
|
||||
#include "nymeasettings.h"
|
||||
#include "logging/logengine.h"
|
||||
@ -76,6 +77,8 @@ ScriptEngine::ScriptEngine(ThingManager *thingManager, LogEngine *logEngine, QOb
|
||||
qmlRegisterType<ScriptAlarm>("nymea", 1, 0, "Alarm");
|
||||
qmlRegisterType<ScriptThing>("nymea", 1, 0, "Thing");
|
||||
qmlRegisterType<ScriptThings>("nymea", 1, 0, "Things");
|
||||
qmlRegisterUncreatableType<Action>("nymea", 1, 0, "Action", "Cannot create Actions. Use ThingAction instead.");
|
||||
|
||||
|
||||
m_logger = logEngine->registerLogSource("scripts", {"id", "event"});
|
||||
|
||||
|
||||
@ -170,6 +170,22 @@ void ScriptThing::init(ThingManager *thingManager)
|
||||
// Note: Explicitly convert the params to a Json document because auto-casting from QVariantMap to the JS engine might drop some values.
|
||||
emit eventTriggered(thing->thingClass().eventTypes().findById(event.eventTypeId()).name(), QJsonDocument::fromVariant(params).toVariant().toMap());
|
||||
});
|
||||
connect(m_thingManager, &ThingManager::actionExecuted, this, [=](const Action &action, Thing::ThingError status){
|
||||
if (m_thingId != action.thingId()) {
|
||||
return;
|
||||
}
|
||||
|
||||
Thing *thing = m_thingManager->findConfiguredThing(action.thingId());
|
||||
QVariantMap params;
|
||||
foreach (const Param ¶m, action.params()) {
|
||||
params.insert(param.paramTypeId().toString().remove(QRegExp("[{}]")), param.value().toByteArray());
|
||||
QString paramName = thing->thingClass().actionTypes().findById(action.actionTypeId()).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 actionExecuted(thing->thingClass().actionTypes().findById(action.actionTypeId()).name(), QJsonDocument::fromVariant(params).toVariant().toMap(), status, action.triggeredBy());
|
||||
});
|
||||
}
|
||||
|
||||
void ScriptThing::connectToThing()
|
||||
|
||||
@ -45,6 +45,8 @@ class ScriptThing : public QObject, public QQmlParserStatus
|
||||
Q_PROPERTY(QString thingId READ thingId WRITE setThingId NOTIFY thingIdChanged)
|
||||
Q_PROPERTY(QString name READ name NOTIFY nameChanged)
|
||||
public:
|
||||
Q_ENUM(Thing::ThingError)
|
||||
|
||||
explicit ScriptThing(QObject *parent = nullptr);
|
||||
explicit ScriptThing(ThingManager *thingManager, QObject *parent = nullptr);
|
||||
void classBegin() override;
|
||||
@ -66,6 +68,7 @@ signals:
|
||||
|
||||
void stateValueChanged(const QString &stateName, const QVariant &value);
|
||||
void eventTriggered(const QString &eventName, const QVariantMap ¶ms);
|
||||
void actionExecuted(const QString &actionName, const QVariantMap ¶ms, Thing::ThingError status, Action::TriggeredBy triggeredBy);
|
||||
|
||||
private slots:
|
||||
void init(ThingManager *thingManager);
|
||||
|
||||
@ -77,4 +77,6 @@ private:
|
||||
TriggeredBy m_triggeredBy = TriggeredByUser;
|
||||
};
|
||||
|
||||
Q_DECLARE_METATYPE(Action::TriggeredBy)
|
||||
|
||||
#endif // ACTION_H
|
||||
|
||||
@ -50,6 +50,11 @@ void TestHelper::logStateChange(const QString &thingId, const QString &stateId,
|
||||
emit stateChangeLogged(ThingId(thingId), stateId, value);
|
||||
}
|
||||
|
||||
void TestHelper::logActionExecuted(const QString &thingId, const QString &actionId, const QVariantMap ¶ms, Thing::ThingError status, Action::TriggeredBy triggeredBy)
|
||||
{
|
||||
emit actionExecutionLogged(ThingId(thingId), actionId, params, status, triggeredBy);
|
||||
}
|
||||
|
||||
void TestHelper::setTestResult(bool success)
|
||||
{
|
||||
emit testResult(success);
|
||||
|
||||
@ -24,6 +24,8 @@
|
||||
#include <QObject>
|
||||
|
||||
#include "typeutils.h"
|
||||
#include "integrations/thing.h"
|
||||
#include "types/action.h"
|
||||
|
||||
class TestHelper : public QObject
|
||||
{
|
||||
@ -33,6 +35,7 @@ public:
|
||||
|
||||
Q_INVOKABLE void logEvent(const QString &thingId, const QString &eventId, const QVariantMap ¶ms);
|
||||
Q_INVOKABLE void logStateChange(const QString &thingId, const QString &stateId, const QVariant &value);
|
||||
Q_INVOKABLE void logActionExecuted(const QString &thingId, const QString &actionId, const QVariantMap ¶ms, Thing::ThingError status, Action::TriggeredBy triggeredBy);
|
||||
|
||||
Q_INVOKABLE void setTestResult(bool success);
|
||||
|
||||
@ -41,7 +44,8 @@ signals:
|
||||
void executeAction(const QVariantMap ¶ms);
|
||||
|
||||
void eventLogged(const ThingId &thingId, const QString &eventId, const QVariantMap ¶ms);
|
||||
void stateChangeLogged(const ThingId &thingId, const QString stateId, const QVariant &value);
|
||||
void stateChangeLogged(const ThingId &thingId, const QString &stateId, const QVariant &value);
|
||||
void actionExecutionLogged(const ThingId &thingId, const QString &actionId, const QVariantMap ¶ms, Thing::ThingError status, Action::TriggeredBy triggeredBy);
|
||||
|
||||
void testResult(bool success);
|
||||
|
||||
|
||||
@ -101,7 +101,9 @@ void TestScripts::init()
|
||||
// Set initial state values of mock device
|
||||
Action action(mockPowerActionTypeId, m_mockThingId);
|
||||
action.setParams(ParamList() << Param(mockPowerActionPowerParamTypeId, false));
|
||||
NymeaCore::instance()->thingManager()->executeAction(action);
|
||||
ThingActionInfo *info = NymeaCore::instance()->thingManager()->executeAction(action);
|
||||
QSignalSpy spy(info, &ThingActionInfo::finished);
|
||||
spy.wait();
|
||||
}
|
||||
|
||||
void TestScripts::testScriptEventById()
|
||||
@ -336,6 +338,9 @@ void TestScripts::testScriptActionById()
|
||||
" id: thingAction\n"
|
||||
" thingId: \"%1\"\n"
|
||||
" actionTypeId: \"%2\"\n"
|
||||
" onExecuted: {\n"
|
||||
" TestHelper.logActionExecuted(\"%1\", \"%2\", params, status, triggeredBy)\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
" Connections {\n"
|
||||
" target: TestHelper\n"
|
||||
@ -350,6 +355,7 @@ void TestScripts::testScriptActionById()
|
||||
QCOMPARE(reply.scriptError, ScriptEngine::ScriptErrorNoError);
|
||||
|
||||
QSignalSpy spy(NymeaCore::instance()->thingManager(), &ThingManager::thingStateChanged);
|
||||
QSignalSpy actionExecutedSpy(TestHelper::instance(), &TestHelper::actionExecutionLogged);
|
||||
|
||||
QVariantMap params;
|
||||
params.insert(mockPowerActionPowerParamTypeId.toString(), true);
|
||||
@ -361,6 +367,13 @@ void TestScripts::testScriptActionById()
|
||||
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);
|
||||
|
||||
QCOMPARE(actionExecutedSpy.count(), 1);
|
||||
QCOMPARE(actionExecutedSpy.first().at(0).value<ThingId>(), m_mockThingId);
|
||||
QCOMPARE(ActionTypeId(actionExecutedSpy.first().at(1).toString()), mockPowerActionTypeId);
|
||||
QCOMPARE(actionExecutedSpy.first().at(2).toMap().value(mockPowerActionTypeId.toString().remove(QRegExp("[{}]"))).toBool(), true);
|
||||
QCOMPARE(actionExecutedSpy.first().at(3).value<Thing::ThingError>(), Thing::ThingErrorNoError);
|
||||
QCOMPARE(actionExecutedSpy.first().at(4).value<Action::TriggeredBy>(), Action::TriggeredByScript);
|
||||
}
|
||||
|
||||
void TestScripts::testScriptActionByName()
|
||||
@ -372,6 +385,9 @@ void TestScripts::testScriptActionByName()
|
||||
" id: thingAction\n"
|
||||
" thingId: \"%1\"\n"
|
||||
" actionName: \"%2\"\n"
|
||||
" onExecuted: {\n"
|
||||
" TestHelper.logActionExecuted(\"%1\", \"%2\", params, status, triggeredBy)\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
" Connections {\n"
|
||||
" target: TestHelper\n"
|
||||
@ -386,6 +402,7 @@ void TestScripts::testScriptActionByName()
|
||||
QCOMPARE(reply.scriptError, ScriptEngine::ScriptErrorNoError);
|
||||
|
||||
QSignalSpy spy(NymeaCore::instance()->thingManager(), &ThingManager::thingStateChanged);
|
||||
QSignalSpy actionExecutedSpy(TestHelper::instance(), &TestHelper::actionExecutionLogged);
|
||||
|
||||
QVariantMap params;
|
||||
params.insert("power", true);
|
||||
@ -397,6 +414,13 @@ void TestScripts::testScriptActionByName()
|
||||
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);
|
||||
|
||||
QCOMPARE(actionExecutedSpy.count(), 1);
|
||||
QCOMPARE(actionExecutedSpy.first().at(0).value<ThingId>(), m_mockThingId);
|
||||
QCOMPARE(actionExecutedSpy.first().at(1).toString(), "power");
|
||||
QCOMPARE(actionExecutedSpy.first().at(2).toMap().value("power").toBool(), true);
|
||||
QCOMPARE(actionExecutedSpy.first().at(3).value<Thing::ThingError>(), Thing::ThingErrorNoError);
|
||||
QCOMPARE(actionExecutedSpy.first().at(4).value<Action::TriggeredBy>(), Action::TriggeredByScript);
|
||||
}
|
||||
|
||||
void TestScripts::testScriptAlarm_data()
|
||||
@ -535,6 +559,9 @@ void TestScripts::testScriptThingAction()
|
||||
" Thing {\n"
|
||||
" id: thing\n"
|
||||
" thingId: \"%1\"\n"
|
||||
" onActionExecuted: {\n"
|
||||
" TestHelper.logActionExecuted(\"%1\", actionName, params, status, triggeredBy)\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
" Connections {\n"
|
||||
" target: TestHelper\n"
|
||||
@ -549,6 +576,7 @@ void TestScripts::testScriptThingAction()
|
||||
QCOMPARE(reply.scriptError, ScriptEngine::ScriptErrorNoError);
|
||||
|
||||
QSignalSpy spy(NymeaCore::instance()->thingManager(), &ThingManager::thingStateChanged);
|
||||
QSignalSpy actionExecutedSpy(TestHelper::instance(), &TestHelper::actionExecutionLogged);
|
||||
|
||||
QVariantMap params;
|
||||
params.insert("power", true);
|
||||
@ -561,6 +589,13 @@ void TestScripts::testScriptThingAction()
|
||||
QCOMPARE(spy.first().at(1).value<StateTypeId>(), mockPowerStateTypeId);
|
||||
QCOMPARE(spy.first().at(2).toBool(), true);
|
||||
|
||||
QCOMPARE(actionExecutedSpy.count(), 1);
|
||||
QCOMPARE(actionExecutedSpy.first().at(0).value<ThingId>(), m_mockThingId);
|
||||
QCOMPARE(actionExecutedSpy.first().at(1).toString(), "power");
|
||||
QCOMPARE(actionExecutedSpy.first().at(2).toMap().value("power").toBool(), true);
|
||||
QCOMPARE(actionExecutedSpy.first().at(3).value<Thing::ThingError>(), Thing::ThingErrorNoError);
|
||||
QCOMPARE(actionExecutedSpy.first().at(4).value<Action::TriggeredBy>(), Action::TriggeredByScript);
|
||||
|
||||
}
|
||||
|
||||
void TestScripts::testScriptThingReadState()
|
||||
|
||||
Reference in New Issue
Block a user