Some more work on the script engine
This commit is contained in:
parent
0f75be0fa4
commit
d4081195d4
@ -25,7 +25,10 @@ HEADERS += nymeacore.h \
|
||||
ruleengine/stateevaluator.h \
|
||||
ruleengine/ruleaction.h \
|
||||
ruleengine/ruleactionparam.h \
|
||||
scriptengine/scriptaction.h \
|
||||
scriptengine/scriptengine.h \
|
||||
scriptengine/scriptevent.h \
|
||||
scriptengine/scriptstate.h \
|
||||
transportinterface.h \
|
||||
nymeaconfiguration.h \
|
||||
servermanager.h \
|
||||
@ -100,7 +103,10 @@ SOURCES += nymeacore.cpp \
|
||||
ruleengine/stateevaluator.cpp \
|
||||
ruleengine/ruleaction.cpp \
|
||||
ruleengine/ruleactionparam.cpp \
|
||||
scriptengine/scriptaction.cpp \
|
||||
scriptengine/scriptengine.cpp \
|
||||
scriptengine/scriptevent.cpp \
|
||||
scriptengine/scriptstate.cpp \
|
||||
transportinterface.cpp \
|
||||
nymeaconfiguration.cpp \
|
||||
servermanager.cpp \
|
||||
|
||||
@ -663,6 +663,7 @@ QStringList NymeaCore::loggingFilters()
|
||||
"DeviceManager",
|
||||
"RuleEngine",
|
||||
"RuleEngineDebug",
|
||||
"ScriptEngine",
|
||||
"Hardware",
|
||||
"Bluetooth",
|
||||
"LogEngine",
|
||||
|
||||
64
libnymea-core/scriptengine/scriptaction.cpp
Normal file
64
libnymea-core/scriptengine/scriptaction.cpp
Normal file
@ -0,0 +1,64 @@
|
||||
#include "scriptaction.h"
|
||||
|
||||
#include "devices/devicemanager.h"
|
||||
#include "types/action.h"
|
||||
|
||||
#include <QQmlEngine>
|
||||
|
||||
namespace nymeaserver {
|
||||
|
||||
ScriptAction::ScriptAction(QObject *parent) : QObject(parent)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void ScriptAction::classBegin()
|
||||
{
|
||||
m_deviceManager = reinterpret_cast<DeviceManager*>(qmlEngine(this)->property("deviceManager").toULongLong());
|
||||
}
|
||||
|
||||
void ScriptAction::componentComplete()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
QString ScriptAction::deviceId() const
|
||||
{
|
||||
return m_deviceId;
|
||||
}
|
||||
|
||||
void ScriptAction::setDeviceId(const QString &deviceId)
|
||||
{
|
||||
if (m_deviceId != deviceId) {
|
||||
m_deviceId = deviceId;
|
||||
emit deviceIdChanged();
|
||||
}
|
||||
}
|
||||
|
||||
QString ScriptAction::actionTypeId() const
|
||||
{
|
||||
return m_actionTypeId;
|
||||
}
|
||||
|
||||
void ScriptAction::setActionTypeId(const QString &actionTypeId)
|
||||
{
|
||||
if (m_actionTypeId != actionTypeId) {
|
||||
m_actionTypeId = actionTypeId;
|
||||
emit actionTypeIdChanged();
|
||||
}
|
||||
}
|
||||
|
||||
void ScriptAction::execute(const QVariantList ¶ms)
|
||||
{
|
||||
Action action;
|
||||
action.setActionTypeId(ActionTypeId(m_actionTypeId));
|
||||
action.setDeviceId(DeviceId(m_deviceId));
|
||||
ParamList paramList;
|
||||
foreach (const QVariant &p, params) {
|
||||
paramList << Param(ParamTypeId(p.toMap().value("paramTypeId").toUuid()), p.toMap().value("value"));
|
||||
}
|
||||
action.setParams(paramList);
|
||||
m_deviceManager->executeAction(action);
|
||||
}
|
||||
|
||||
}
|
||||
42
libnymea-core/scriptengine/scriptaction.h
Normal file
42
libnymea-core/scriptengine/scriptaction.h
Normal file
@ -0,0 +1,42 @@
|
||||
#ifndef SCRIPTACTION_H
|
||||
#define SCRIPTACTION_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QQmlParserStatus>
|
||||
|
||||
class DeviceManager;
|
||||
|
||||
namespace nymeaserver {
|
||||
|
||||
class ScriptAction : public QObject, public QQmlParserStatus
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(QString deviceId READ deviceId WRITE setDeviceId NOTIFY deviceIdChanged)
|
||||
Q_PROPERTY(QString actionTypeId READ actionTypeId WRITE setActionTypeId NOTIFY actionTypeIdChanged)
|
||||
public:
|
||||
explicit ScriptAction(QObject *parent = nullptr);
|
||||
void classBegin() override;
|
||||
void componentComplete() override;
|
||||
|
||||
QString deviceId() const;
|
||||
void setDeviceId(const QString &deviceId);
|
||||
|
||||
QString actionTypeId() const;
|
||||
void setActionTypeId(const QString &actionTypeId);
|
||||
|
||||
public slots:
|
||||
void execute(const QVariantList ¶ms);
|
||||
|
||||
signals:
|
||||
void deviceIdChanged();
|
||||
void actionTypeIdChanged();
|
||||
|
||||
public:
|
||||
DeviceManager *m_deviceManager = nullptr;
|
||||
QString m_deviceId;
|
||||
QString m_actionTypeId;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // SCRIPTACTION_H
|
||||
@ -1,6 +1,10 @@
|
||||
#include "scriptengine.h"
|
||||
#include "devices/devicemanager.h"
|
||||
|
||||
#include "scriptaction.h"
|
||||
#include "scriptevent.h"
|
||||
#include "scriptstate.h"
|
||||
|
||||
#include <QQmlApplicationEngine>
|
||||
|
||||
namespace nymeaserver {
|
||||
@ -8,13 +12,19 @@ namespace nymeaserver {
|
||||
ScriptEngine::ScriptEngine(DeviceManager *deviceManager, QObject *parent) : QObject(parent),
|
||||
m_deviceManager(deviceManager)
|
||||
{
|
||||
qmlRegisterType<ScriptEvent>("nymea", 1, 0, "Event");
|
||||
qmlRegisterType<ScriptAction>("nymea", 1, 0, "Action");
|
||||
qmlRegisterType<ScriptState>("nymea", 1, 0, "State");
|
||||
|
||||
loadScripts();
|
||||
}
|
||||
|
||||
void ScriptEngine::loadScripts()
|
||||
{
|
||||
QString fileName = "/home/micha/Develop/nymea/tests/script.qml";
|
||||
|
||||
QQmlApplicationEngine *engine = new QQmlApplicationEngine(this);
|
||||
engine->setProperty("deviceManager", reinterpret_cast<quint64>(m_deviceManager));
|
||||
|
||||
engine->load(fileName);
|
||||
}
|
||||
|
||||
@ -2,8 +2,10 @@
|
||||
#define SCRIPTENGINE_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QUuid>
|
||||
#include <QQmlEngine>
|
||||
|
||||
class DeviceManager;
|
||||
#include "devices/devicemanager.h"
|
||||
|
||||
namespace nymeaserver {
|
||||
|
||||
|
||||
78
libnymea-core/scriptengine/scriptevent.cpp
Normal file
78
libnymea-core/scriptengine/scriptevent.cpp
Normal file
@ -0,0 +1,78 @@
|
||||
#include "scriptevent.h"
|
||||
|
||||
namespace nymeaserver {
|
||||
|
||||
ScriptEvent::ScriptEvent(QObject *parent) : QObject(parent)
|
||||
{
|
||||
}
|
||||
|
||||
void ScriptEvent::classBegin()
|
||||
{
|
||||
m_deviceManager = reinterpret_cast<DeviceManager*>(qmlEngine(this)->property("deviceManager").toULongLong());
|
||||
connect(m_deviceManager, &DeviceManager::eventTriggered, this, &ScriptEvent::onEventTriggered);
|
||||
}
|
||||
|
||||
void ScriptEvent::componentComplete()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
QString ScriptEvent::deviceId() const
|
||||
{
|
||||
return m_deviceId;
|
||||
}
|
||||
|
||||
void ScriptEvent::setDeviceId(const QString &deviceId)
|
||||
{
|
||||
if (m_deviceId != deviceId) {
|
||||
m_deviceId = deviceId;
|
||||
emit deviceIdChanged();
|
||||
}
|
||||
}
|
||||
|
||||
QString ScriptEvent::eventTypeId() const
|
||||
{
|
||||
return m_eventTypeId;
|
||||
}
|
||||
|
||||
void ScriptEvent::setEventTypeId(const QString &eventTypeId)
|
||||
{
|
||||
if (m_eventTypeId != eventTypeId) {
|
||||
m_eventTypeId = eventTypeId;
|
||||
emit eventTypeIdChanged();
|
||||
}
|
||||
}
|
||||
|
||||
QString ScriptEvent::eventName() const
|
||||
{
|
||||
return m_eventName;
|
||||
}
|
||||
|
||||
void ScriptEvent::setEventName(const QString &eventName)
|
||||
{
|
||||
if (m_eventName != eventName) {
|
||||
m_eventName = eventName;
|
||||
emit eventNameChanged();
|
||||
}
|
||||
}
|
||||
|
||||
void ScriptEvent::onEventTriggered(const Event &event)
|
||||
{
|
||||
if (QUuid(m_deviceId) != event.deviceId()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!m_eventTypeId.isEmpty() && event.eventTypeId() != m_eventTypeId) {
|
||||
return;
|
||||
}
|
||||
|
||||
Device *device = m_deviceManager->findConfiguredDevice(event.deviceId());
|
||||
if (!m_eventName.isEmpty() && device->deviceClass().eventTypes().findByName(m_eventName).id() != event.eventTypeId()) {
|
||||
return;
|
||||
}
|
||||
|
||||
emit triggered();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
54
libnymea-core/scriptengine/scriptevent.h
Normal file
54
libnymea-core/scriptengine/scriptevent.h
Normal file
@ -0,0 +1,54 @@
|
||||
#ifndef EVENTLISTENER_H
|
||||
#define EVENTLISTENER_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QUuid>
|
||||
#include <QQmlEngine>
|
||||
|
||||
#include "types/event.h"
|
||||
#include "devices/devicemanager.h"
|
||||
|
||||
namespace nymeaserver {
|
||||
|
||||
class ScriptEvent: public QObject, public QQmlParserStatus
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_INTERFACES(QQmlParserStatus)
|
||||
Q_PROPERTY(QString deviceId READ deviceId WRITE setDeviceId NOTIFY deviceIdChanged)
|
||||
Q_PROPERTY(QString eventTypeId READ eventTypeId WRITE setEventTypeId NOTIFY eventTypeIdChanged)
|
||||
Q_PROPERTY(QString eventName READ eventName WRITE setEventName NOTIFY eventNameChanged)
|
||||
public:
|
||||
ScriptEvent(QObject *parent = nullptr);
|
||||
void classBegin() override;
|
||||
void componentComplete() override;
|
||||
|
||||
QString deviceId() const;
|
||||
void setDeviceId(const QString &deviceId);
|
||||
|
||||
QString eventTypeId() const;
|
||||
void setEventTypeId(const QString &eventTypeId);
|
||||
|
||||
QString eventName() const;
|
||||
void setEventName(const QString &eventName);
|
||||
|
||||
private slots:
|
||||
void onEventTriggered(const Event &event);
|
||||
|
||||
signals:
|
||||
void deviceIdChanged();
|
||||
void eventTypeIdChanged();
|
||||
void eventNameChanged();
|
||||
|
||||
void triggered();
|
||||
|
||||
private:
|
||||
DeviceManager *m_deviceManager = nullptr;
|
||||
|
||||
QString m_deviceId;
|
||||
QString m_eventTypeId;
|
||||
QString m_eventName;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // EVENTLISTENER_H
|
||||
116
libnymea-core/scriptengine/scriptstate.cpp
Normal file
116
libnymea-core/scriptengine/scriptstate.cpp
Normal file
@ -0,0 +1,116 @@
|
||||
#include "scriptstate.h"
|
||||
|
||||
#include "loggingcategories.h"
|
||||
|
||||
#include <QColor>
|
||||
|
||||
namespace nymeaserver {
|
||||
|
||||
ScriptState::ScriptState(QObject *parent) : QObject(parent)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void ScriptState::classBegin()
|
||||
{
|
||||
m_deviceManager = reinterpret_cast<DeviceManager*>(qmlEngine(this)->property("deviceManager").toULongLong());
|
||||
connect(m_deviceManager, &DeviceManager::deviceStateChanged, this, &ScriptState::onDeviceStateChanged);
|
||||
}
|
||||
|
||||
void ScriptState::componentComplete()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
QString ScriptState::deviceId() const
|
||||
{
|
||||
return m_deviceId;
|
||||
}
|
||||
|
||||
void ScriptState::setDeviceId(const QString &deviceId)
|
||||
{
|
||||
if (m_deviceId != deviceId) {
|
||||
m_deviceId = deviceId;
|
||||
emit deviceIdChanged();
|
||||
store();
|
||||
}
|
||||
}
|
||||
|
||||
QString ScriptState::stateTypeId() const
|
||||
{
|
||||
return m_stateTypeId;
|
||||
}
|
||||
|
||||
void ScriptState::setStateTypeId(const QString &stateTypeId)
|
||||
{
|
||||
if (m_stateTypeId != stateTypeId) {
|
||||
m_stateTypeId = stateTypeId;
|
||||
emit stateTypeIdChanged();
|
||||
store();
|
||||
}
|
||||
}
|
||||
|
||||
QVariant ScriptState::value() const
|
||||
{
|
||||
Device* device = m_deviceManager->findConfiguredDevice(DeviceId(m_deviceId));
|
||||
if (!device) {
|
||||
return QVariant();
|
||||
}
|
||||
return device->stateValue(StateTypeId(m_stateTypeId));
|
||||
}
|
||||
|
||||
void ScriptState::setValue(const QVariant &value)
|
||||
{
|
||||
qCDebug(dcScriptEngine()) << "setValueCalled1" << value;
|
||||
if (m_pendingActionInfo) {
|
||||
m_valueCache = value;
|
||||
return;
|
||||
}
|
||||
|
||||
Device* device = m_deviceManager->findConfiguredDevice(DeviceId(m_deviceId));
|
||||
if (!device) {
|
||||
qCWarning(dcScriptEngine()) << "No device with id" << m_deviceId << "found.";
|
||||
return;
|
||||
}
|
||||
|
||||
if (device->deviceClass().stateTypes().findById(StateTypeId(m_stateTypeId)).id().isNull()) {
|
||||
qCWarning(dcScriptEngine) << "Device" << device->name() << "does not have a state with type id" << m_stateTypeId;
|
||||
return;
|
||||
}
|
||||
Action action;
|
||||
action.setDeviceId(DeviceId(m_deviceId));
|
||||
action.setActionTypeId(ActionTypeId(m_stateTypeId));
|
||||
ParamList params = ParamList() << Param(ParamTypeId(m_stateTypeId), value);
|
||||
action.setParams(params);
|
||||
|
||||
qCDebug(dcScriptEngine()) << "setValueCalled2" << value;
|
||||
m_valueCache = QVariant();
|
||||
m_pendingActionInfo = m_deviceManager->executeAction(action);
|
||||
connect(m_pendingActionInfo, &DeviceActionInfo::finished, this, [this](){
|
||||
m_pendingActionInfo = nullptr;
|
||||
if (!m_valueCache.isNull()) {
|
||||
setValue(m_valueCache);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void ScriptState::store()
|
||||
{
|
||||
m_valueStore = value();
|
||||
qCDebug(dcScriptEngine()) << "Storing value:" << m_valueStore;
|
||||
}
|
||||
|
||||
void ScriptState::restore()
|
||||
{
|
||||
qCDebug(dcScriptEngine()) << "Restoring value:" << m_valueStore << m_valueStore.value<QColor>().toRgb();
|
||||
setValue(m_valueStore);
|
||||
}
|
||||
|
||||
void nymeaserver::ScriptState::onDeviceStateChanged(Device *device, const StateTypeId &stateTypeId)
|
||||
{
|
||||
if (device->id() == DeviceId(m_deviceId) && stateTypeId == StateTypeId(m_stateTypeId)) {
|
||||
emit valueChanged();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
63
libnymea-core/scriptengine/scriptstate.h
Normal file
63
libnymea-core/scriptengine/scriptstate.h
Normal file
@ -0,0 +1,63 @@
|
||||
#ifndef SCRIPTSTATE_H
|
||||
#define SCRIPTSTATE_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QQmlEngine>
|
||||
#include <QPointer>
|
||||
|
||||
#include "devices/devicemanager.h"
|
||||
#include "devices/deviceactioninfo.h"
|
||||
|
||||
namespace nymeaserver {
|
||||
|
||||
class ScriptState : public QObject, public QQmlParserStatus
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_INTERFACES(QQmlParserStatus)
|
||||
Q_PROPERTY(QString deviceId READ deviceId WRITE setDeviceId NOTIFY deviceIdChanged)
|
||||
Q_PROPERTY(QString stateTypeId READ stateTypeId WRITE setStateTypeId NOTIFY stateTypeIdChanged)
|
||||
Q_PROPERTY(QString stateName READ stateName WRITE setStateName NOTIFY stateNameChanged)
|
||||
Q_PROPERTY(QVariant value READ value WRITE setValue NOTIFY valueChanged)
|
||||
|
||||
public:
|
||||
explicit ScriptState(QObject *parent = nullptr);
|
||||
void classBegin() override;
|
||||
void componentComplete() override;
|
||||
|
||||
QString deviceId() const;
|
||||
void setDeviceId(const QString &deviceId);
|
||||
|
||||
QString stateTypeId() const;
|
||||
void setStateTypeId(const QString &stateTypeId);
|
||||
|
||||
QVariant value() const;
|
||||
void setValue(const QVariant &value);
|
||||
|
||||
public slots:
|
||||
void store();
|
||||
void restore();
|
||||
|
||||
signals:
|
||||
void deviceIdChanged();
|
||||
void stateTypeIdChanged();
|
||||
void stateNameChanged();
|
||||
void valueChanged();
|
||||
|
||||
private slots:
|
||||
void onDeviceStateChanged(Device *device, const StateTypeId &stateTypeId);
|
||||
|
||||
private:
|
||||
DeviceManager *m_deviceManager = nullptr;
|
||||
|
||||
QString m_deviceId;
|
||||
QString m_stateTypeId;
|
||||
|
||||
DeviceActionInfo *m_pendingActionInfo = nullptr;
|
||||
QVariant m_valueCache;
|
||||
|
||||
QVariant m_valueStore;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // SCRIPTSTATE_H
|
||||
@ -34,6 +34,7 @@ Q_LOGGING_CATEGORY(dcExperiences, "Experiences")
|
||||
Q_LOGGING_CATEGORY(dcTimeManager, "TimeManager")
|
||||
Q_LOGGING_CATEGORY(dcRuleEngine, "RuleEngine")
|
||||
Q_LOGGING_CATEGORY(dcRuleEngineDebug, "RuleEngineDebug")
|
||||
Q_LOGGING_CATEGORY(dcScriptEngine, "ScriptEngine")
|
||||
Q_LOGGING_CATEGORY(dcHardware, "Hardware")
|
||||
Q_LOGGING_CATEGORY(dcLogEngine, "LogEngine")
|
||||
Q_LOGGING_CATEGORY(dcServerManager, "ServerManager")
|
||||
|
||||
@ -39,6 +39,7 @@ Q_DECLARE_LOGGING_CATEGORY(dcExperiences)
|
||||
Q_DECLARE_LOGGING_CATEGORY(dcTimeManager)
|
||||
Q_DECLARE_LOGGING_CATEGORY(dcRuleEngine)
|
||||
Q_DECLARE_LOGGING_CATEGORY(dcRuleEngineDebug)
|
||||
Q_DECLARE_LOGGING_CATEGORY(dcScriptEngine)
|
||||
Q_DECLARE_LOGGING_CATEGORY(dcHardware)
|
||||
Q_DECLARE_LOGGING_CATEGORY(dcLogEngine)
|
||||
Q_DECLARE_LOGGING_CATEGORY(dcServerManager)
|
||||
|
||||
@ -6,14 +6,14 @@ if [ -z $1 ]; then
|
||||
fi
|
||||
|
||||
if [ -z $2 ]; then
|
||||
cat <<EOD | nc $1 2222 | jq
|
||||
cat <<EOD | nc $1 2222
|
||||
{"id":0, "method":"JSONRPC.Hello"}
|
||||
{"id":1, "method":"Devices.GetConfiguredDevices"}
|
||||
EOD
|
||||
exit 0
|
||||
fi
|
||||
|
||||
cat <<EOD | nc $1 2222 | jq
|
||||
cat <<EOD | nc $1 2222
|
||||
{"id":0, "method":"JSONRPC.Hello"}
|
||||
{"id":1, "token": "$2", "method":"Devices.GetConfiguredDevices"}
|
||||
EOD
|
||||
|
||||
@ -2,6 +2,10 @@
|
||||
|
||||
if [ -z $2 ]; then
|
||||
echo "usage: $0 host deviceClassId"
|
||||
else
|
||||
(echo '{"id":1, "method":"Devices.GetStateTypes", "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.GetStateTypes", "params":{"deviceClassId":"$2"}}
|
||||
EOD
|
||||
|
||||
Reference in New Issue
Block a user