diff --git a/libnymea-app-core/devicemanager.cpp b/libnymea-app-core/devicemanager.cpp index 7cd02d87..d647a182 100644 --- a/libnymea-app-core/devicemanager.cpp +++ b/libnymea-app-core/devicemanager.cpp @@ -241,7 +241,7 @@ void DeviceManager::getConfiguredDevicesResponse(const QVariantMap ¶ms) device->setStateValue(stateTypeId, value); // qDebug() << "Set device state value:" << device->stateValue(stateTypeId) << value; } - qDebug() << "Confgured Device JSON:" << qUtf8Printable(QJsonDocument::fromVariant(deviceVariant).toJson(QJsonDocument::Indented)); +// qDebug() << "Configured Device JSON:" << qUtf8Printable(QJsonDocument::fromVariant(deviceVariant).toJson(QJsonDocument::Indented)); devices()->addDevice(device); qDebug() << "*** Added device:" << endl << device; } diff --git a/libnymea-app-core/rulemanager.cpp b/libnymea-app-core/rulemanager.cpp index 563f514f..daa7b192 100644 --- a/libnymea-app-core/rulemanager.cpp +++ b/libnymea-app-core/rulemanager.cpp @@ -168,7 +168,7 @@ void RuleManager::getRuleDetailsReply(const QVariantMap ¶ms) void RuleManager::onAddRuleReply(const QVariantMap ¶ms) { - qDebug() << "Add rule reply:" << params.value("params").toMap().value("ruleError").toString(); + qDebug() << "Add rule reply:" << params;//.value("params").toMap().value("ruleError").toString(); emit addRuleReply(params.value("params").toMap().value("ruleError").toString(), params.value("params").toMap().value("ruleId").toString()); } diff --git a/libnymea-app-core/ruletemplates/ruletemplates.cpp b/libnymea-app-core/ruletemplates/ruletemplates.cpp index 41e2d549..f543aaed 100644 --- a/libnymea-app-core/ruletemplates/ruletemplates.cpp +++ b/libnymea-app-core/ruletemplates/ruletemplates.cpp @@ -62,6 +62,12 @@ RuleTemplates::RuleTemplates(QObject *parent) : QAbstractListModel(parent) evpt->setParamName(eventDescriptorParamTemplate.value("name").toString()); if (eventDescriptorParamTemplate.contains("value")) { evpt->setValue(eventDescriptorParamTemplate.value("value")); + if (!eventDescriptorParamTemplate.contains("operator")) { + qWarning() << "BROKEN Template: Operator missing for event descriptor template" << qUtf8Printable(QJsonDocument::fromVariant(eventDescriptorParamTemplate).toJson(QJsonDocument::Indented)); + } else { + QMetaEnum operatorEnum = QMetaEnum::fromType(); + evpt->setOperatorType(static_cast(operatorEnum.keyToValue(eventDescriptorParamTemplate.value("operator").toByteArray().data()))); + } } evt->paramDescriptors()->addParamDescriptor(evpt); } @@ -144,9 +150,9 @@ RuleTemplates::RuleTemplates(QObject *parent) : QAbstractListModel(parent) t->ruleExitActionTemplates()->addRuleActionTemplate(rat); } - qDebug() << "Added rule template:" << t->ruleActionTemplates()->rowCount(); m_list.append(t); } +// qDebug() << "Loaded" << m_list.count() << "rule templates"; } } @@ -187,7 +193,7 @@ bool RuleTemplatesFilterModel::filterAcceptsRow(int source_row, const QModelInde return false; } RuleTemplate *t = m_ruleTemplates->get(source_row); - qDebug() << "Checking interface" << t->description() << t->interfaceName() << "for usage with:" << m_filterInterfaceNames; +// qDebug() << "Checking interface" << t->description() << t->interfaceName() << "for usage with:" << m_filterInterfaceNames; if (!m_filterInterfaceNames.isEmpty()) { if (!m_filterInterfaceNames.contains(t->interfaceName())) { return false; diff --git a/libnymea-common/types/interfaces.cpp b/libnymea-common/types/interfaces.cpp index 3546c4de..9916fc0c 100644 --- a/libnymea-common/types/interfaces.cpp +++ b/libnymea-common/types/interfaces.cpp @@ -27,6 +27,11 @@ Interfaces::Interfaces(QObject *parent) : QAbstractListModel(parent) addParamType(pts, "body", tr("Message body"), QVariant::String); addActionType("notifications", "notify", tr("Send notification"), pts); + addInterface("power", tr("Powered things")); + addStateType("power", "power", QVariant::Bool, true, + tr("Thing is turned on"), + tr("A thing is turned on or off"), + tr("Turn things on or off")); addInterface("light", tr("Lights")); addStateType("light", "power", QVariant::Bool, true, diff --git a/nymea-app/nymea-app.pro b/nymea-app/nymea-app.pro index a2b96c44..da237c2c 100644 --- a/nymea-app/nymea-app.pro +++ b/nymea-app/nymea-app.pro @@ -126,5 +126,7 @@ target.path = /usr/bin INSTALLS += target DISTFILES += \ - ruletemplates/smartmetertemplates.json + ruletemplates/smartmetertemplates.json \ + ruletemplates/presencesensortemplates.json \ + ruletemplates/daylightsensor.json diff --git a/nymea-app/ruletemplates.qrc b/nymea-app/ruletemplates.qrc index 24df3a96..579d5223 100644 --- a/nymea-app/ruletemplates.qrc +++ b/nymea-app/ruletemplates.qrc @@ -4,5 +4,7 @@ ruletemplates/notificationtemplates.json ruletemplates/accesscontroltemplates.json ruletemplates/smartmetertemplates.json + ruletemplates/presencesensortemplates.json + ruletemplates/daylightsensor.json diff --git a/nymea-app/ruletemplates/daylightsensor.json b/nymea-app/ruletemplates/daylightsensor.json new file mode 100644 index 00000000..4d1f251d --- /dev/null +++ b/nymea-app/ruletemplates/daylightsensor.json @@ -0,0 +1,110 @@ +{ + "templates": [ + { + "interfaceName": "daylightsensor", + "description": "Turn on a light while it's dark outside.", + "ruleNameTemplate": "Turn on %1 while it's dark outside", + "stateEvaluatorTemplate": { + "stateDescriptorTemplate": { + "interfaceName": "daylightsensor", + "interfaceState": "daylight", + "selectionId": 0, + "operator": "ValueOperatorEquals", + "value": false + } + }, + "ruleActionTemplates": [ + { + "interfaceName": "power", + "interfaceAction": "power", + "selectionId": 1, + "params": [ + { + "name": "power", + "value": "true" + } + ] + } + ], + "ruleExitActionTemplates": [ + { + "interfaceName": "power", + "interfaceAction": "power", + "selectionId": 1, + "params": [ + { + "name": "power", + "value": "false" + } + ] + } + ] + }, + { + "interfaceName": "daylightsensor", + "description": "Turn on a light when it gets dark outside.", + "ruleNameTemplate": "Turn on %1 it gets dark outside (%0).", + "eventDescriptorTemplates": [ + { + "interfaceName": "daylightsensor", + "interfaceEvent": "daylight", + "selectionId": 0, + "params": [ + { + "name": "daylight", + "value": false, + "operator": "ValueOperatorEquals" + } + ] + } + ], + "ruleActionTemplates": [ + { + "interfaceName": "light", + "interfaceAction": "power", + "selectionId": 1, + "params": [ + { + "name": "power", + "value": "true" + } + ] + } + ] + }, + { + "interfaceName": "daylightsensor", + "description": "Turn on all lights when it gets dark outside.", + "ruleNameTemplate": "Turn on all lights when it gets dark outside.", + "eventDescriptorTemplates": [ + { + "interfaceName": "daylightsensor", + "interfaceEvent": "daylight", + "selectionId": 0, + "params": [ + { + "name": "daylight", + "value": false, + "operator": "ValueOperatorEquals" + } + ] + } + ], + "ruleActionTemplates": [ + { + "interfaceName": "light", + "interfaceAction": "power", + "selectionId": 1, + "selectionMode": "SelectionModeInterface", + "params": [ + { + "name": "power", + "value": "true" + } + ] + } + ] + } + ] +} + diff --git a/nymea-app/ruletemplates/presencesensortemplates.json b/nymea-app/ruletemplates/presencesensortemplates.json new file mode 100644 index 00000000..14cccfd3 --- /dev/null +++ b/nymea-app/ruletemplates/presencesensortemplates.json @@ -0,0 +1,175 @@ +{ + "templates": [ + { + "interfaceName": "presencesensor", + "description": "Turn on something while this device is present...", + "ruleNameTemplate": "Turn on %1 while %0 is present", + "stateEvaluatorTemplate": { + "stateDescriptorTemplate": { + "interfaceName": "presencesensor", + "interfaceState": "isPresent", + "selectionId": 0, + "operator": "ValueOperatorEquals", + "value": true + } + }, + "ruleActionTemplates": [ + { + "interfaceName": "power", + "interfaceAction": "power", + "selectionId": 1, + "params": [ + { + "name": "power", + "value": "true" + } + ] + } + ], + "ruleExitActionTemplates": [ + { + "interfaceName": "power", + "interfaceAction": "power", + "selectionId": 1, + "params": [ + { + "name": "power", + "value": "false" + } + ] + } + ] + }, + { + "interfaceName": "presencesensor", + "description": "Turn off something when this device leaves...", + "ruleNameTemplate": "Turn off %1 when %0 leaves", + "eventDescriptorTemplates": [ + { + "interfaceName": "presencesensor", + "interfaceEvent": "isPresent", + "selectionId": 0, + "params": [ + { + "name": "isPresent", + "value": false, + "operator": "ValueOperatorEquals" + } + ] + } + ], + "ruleActionTemplates": [ + { + "interfaceName": "power", + "interfaceAction": "power", + "selectionId": 1, + "params": [ + { + "name": "power", + "value": "false" + } + ] + } + ] + }, + { + "interfaceName": "presencesensor", + "description": "Turn off everything when this device leaves...", + "ruleNameTemplate": "Turn off everything when %0 leaves", + "eventDescriptorTemplates": [ + { + "interfaceName": "presencesensor", + "interfaceEvent": "isPresent", + "selectionId": 0, + "params": [ + { + "name": "isPresent", + "value": false, + "operator": "ValueOperatorEquals" + } + ] + } + ], + "ruleActionTemplates": [ + { + "interfaceName": "power", + "interfaceAction": "power", + "selectionId": 1, + "selectionMode": "SelectionModeInterface", + "params": [ + { + "name": "power", + "value": "false" + } + ] + } + ] + }, + { + "interfaceName": "presencesensor", + "description": "Turn off all lights when this device leaves...", + "ruleNameTemplate": "Turn off all lights when %0 leaves", + "eventDescriptorTemplates": [ + { + "interfaceName": "presencesensor", + "interfaceEvent": "isPresent", + "selectionId": 0, + "params": [ + { + "name": "isPresent", + "value": false, + "operator": "ValueOperatorEquals" + } + ] + } + ], + "ruleActionTemplates": [ + { + "interfaceName": "light", + "interfaceAction": "power", + "selectionId": 1, + "selectionMode": "SelectionModeInterface", + "params": [ + { + "name": "power", + "value": "false" + } + ] + } + ] + }, + { + "interfaceName": "presencesensor", + "description": "Turn on something when this device arrives...", + "ruleNameTemplate": "Turn on %1 when %0 arrives", + "eventDescriptorTemplates": [ + { + "interfaceName": "presencesensor", + "interfaceEvent": "isPresent", + "selectionId": 0, + "params": [ + { + "name": "isPresent", + "value": true, + "operator": "ValueOperatorEquals" + } + ] + } + ], + "ruleActionTemplates": [ + { + "interfaceName": "power", + "interfaceAction": "power", + "selectionId": 1, + "params": [ + { + "name": "power", + "value": "true" + } + ] + } + ] + } + ] +} + diff --git a/nymea-app/ui/Nymea.qml b/nymea-app/ui/Nymea.qml index 2239f8e1..32df5cac 100644 --- a/nymea-app/ui/Nymea.qml +++ b/nymea-app/ui/Nymea.qml @@ -253,6 +253,8 @@ ApplicationWindow { return qsTr("battery powered thing") case "connectable": return qsTr("connectable thing") + case "power": + return qsTr("switchable thing") default: console.warn("Unhandled interfaceToDisplayName:", name) } diff --git a/nymea-app/ui/devicepages/SensorDevicePagePost110.qml b/nymea-app/ui/devicepages/SensorDevicePagePost110.qml index 9044d34f..b70b737b 100644 --- a/nymea-app/ui/devicepages/SensorDevicePagePost110.qml +++ b/nymea-app/ui/devicepages/SensorDevicePagePost110.qml @@ -13,7 +13,6 @@ ListView { Component.onCompleted: { var supportedInterfaces = ["temperaturesensor", "humiditysensor", "pressuresensor", "moisturesensor", "lightsensor", "conductivitysensor", "noisesensor", "co2sensor", "presencesensor", "daylightsensor"] for (var i = 0; i < supportedInterfaces.length; i++) { - print("checking", root.deviceClass.name, root.deviceClass.interfaces) if (root.deviceClass.interfaces.indexOf(supportedInterfaces[i]) >= 0) { append({name: supportedInterfaces[i]}); } diff --git a/nymea-app/ui/magic/EventDescriptorDelegate.qml b/nymea-app/ui/magic/EventDescriptorDelegate.qml index bfc30b1b..63ba021a 100644 --- a/nymea-app/ui/magic/EventDescriptorDelegate.qml +++ b/nymea-app/ui/magic/EventDescriptorDelegate.qml @@ -10,11 +10,11 @@ MeaListItemDelegate { canDelete: true progressive: false - property var eventDescriptor: null - readonly property var device: eventDescriptor ? engine.deviceManager.devices.getDevice(eventDescriptor.deviceId) : null - readonly property var deviceClass: device ? engine.deviceManager.deviceClasses.getDeviceClass(device.deviceClassId) : null - readonly property var iface: eventDescriptor.interfaceName ? Interfaces.findByName(eventDescriptor.interfaceName) : null - readonly property var eventType: deviceClass ? deviceClass.eventTypes.getEventType(eventDescriptor.eventTypeId) + property EventDescriptor eventDescriptor: null + readonly property Device device: eventDescriptor ? engine.deviceManager.devices.getDevice(eventDescriptor.deviceId) : null + readonly property DeviceClass deviceClass: device ? engine.deviceManager.deviceClasses.getDeviceClass(device.deviceClassId) : null + readonly property Interface iface: eventDescriptor.interfaceName ? Interfaces.findByName(eventDescriptor.interfaceName) : null + readonly property EventType eventType: deviceClass ? deviceClass.eventTypes.getEventType(eventDescriptor.eventTypeId) : iface ? iface.eventTypes.findByName(eventDescriptor.interfaceEvent) : null signal removeEventDescriptor() @@ -51,16 +51,20 @@ MeaListItemDelegate { operatorString = " ? "; } + var paramType = paramDescriptor.paramTypeId + ? root.eventType.paramTypes.getParamType(paramDescriptor.paramTypeId) + : root.eventType.paramTypes.findByName(paramDescriptor.paramName) + if (i === 0) { // TRANSLATORS: example: "only if temperature > 5" ret = qsTr("only if %1 %2 %3") - .arg(root.eventType.paramTypes.getParamType(paramDescriptor.paramTypeId).displayName) + .arg(paramType.displayName) .arg(operatorString) .arg(paramDescriptor.value) } else { // TRANSLATORS: example: "and temperature > 5" ret += " " + qsTr("and %1 %2 %3") - .arg(root.eventType.paramTypes.getParamType(paramDescriptor.paramTypeId).displayName) + .arg(paramType.displayName) .arg(operatorString) .arg(model.value) } diff --git a/nymea-app/ui/magic/NewThingMagicPage.qml b/nymea-app/ui/magic/NewThingMagicPage.qml index ae0caa08..95b584b4 100644 --- a/nymea-app/ui/magic/NewThingMagicPage.qml +++ b/nymea-app/ui/magic/NewThingMagicPage.qml @@ -257,7 +257,8 @@ Page { for (var j = 0; j < eventDescriptorTemplate.paramDescriptors.count; j++) { var paramDescriptorTemplate = eventDescriptorTemplate.paramDescriptors.get(j); if (paramDescriptorTemplate.value !== undefined) { - eventDescriptor.paramDescriptors.addParamDescriptor(paramDescriptorTemplate.paramName, paramDescriptorTemplate.value); + print("Adding operator:", paramDescriptorTemplate.operatorType) + eventDescriptor.paramDescriptors.setParamDescriptorByName(paramDescriptorTemplate.paramName, paramDescriptorTemplate.value, paramDescriptorTemplate.operatorType); } else { needsParams = true; }