diff --git a/libnymea-app-core/devices.cpp b/libnymea-app-core/devices.cpp
index d6398282..2b41170a 100644
--- a/libnymea-app-core/devices.cpp
+++ b/libnymea-app-core/devices.cpp
@@ -118,6 +118,15 @@ QVariant Devices::data(const QModelIndex &index, int role) const
if (interfaces.contains("notifications")) {
return "notifications";
}
+ if (interfaces.contains("smartmeter")) {
+ return "smartmeter";
+ }
+ if (interfaces.contains("heating")) {
+ return "heating";
+ }
+ if (interfaces.contains("evcharger")) {
+ return "evcharger";
+ }
return "uncategorized";
}
diff --git a/libnymea-app-core/jsonrpc/jsonrpcclient.cpp b/libnymea-app-core/jsonrpc/jsonrpcclient.cpp
index eddce39f..69656d5d 100644
--- a/libnymea-app-core/jsonrpc/jsonrpcclient.cpp
+++ b/libnymea-app-core/jsonrpc/jsonrpcclient.cpp
@@ -303,7 +303,7 @@ void JsonRpcClient::sendRequest(const QVariantMap &request)
{
QVariantMap newRequest = request;
newRequest.insert("token", m_token);
- qDebug() << "Sending request" << qUtf8Printable(QJsonDocument::fromVariant(newRequest).toJson());
+// qDebug() << "Sending request" << qUtf8Printable(QJsonDocument::fromVariant(newRequest).toJson());
m_connection->sendData(QJsonDocument::fromVariant(newRequest).toJson(QJsonDocument::Compact) + "\n");
}
@@ -340,7 +340,7 @@ void JsonRpcClient::dataReceived(const QByteArray &data)
// qWarning() << "Could not parse json data from nymea" << m_receiveBuffer.left(splitIndex) << error.errorString();
return;
}
- qDebug() << "received response" << qUtf8Printable(jsonDoc.toJson(QJsonDocument::Indented));
+// qDebug() << "received response" << qUtf8Printable(jsonDoc.toJson(QJsonDocument::Indented));
m_receiveBuffer = m_receiveBuffer.right(m_receiveBuffer.length() - splitIndex - 1);
if (!m_receiveBuffer.isEmpty()) {
staticMetaObject.invokeMethod(this, "dataReceived", Qt::QueuedConnection, Q_ARG(QByteArray, QByteArray()));
diff --git a/nymea-app/images.qrc b/nymea-app/images.qrc
index 37ca322f..eac9c6ad 100644
--- a/nymea-app/images.qrc
+++ b/nymea-app/images.qrc
@@ -151,5 +151,7 @@
ui/images/zoom-out.svg
ui/images/zoom-in.svg
ui/images/smartmeter.svg
+ ui/images/radiator.svg
+ ui/images/ev-charger.svg
diff --git a/nymea-app/nymea-app.pro b/nymea-app/nymea-app.pro
index 75da82e2..241270c3 100644
--- a/nymea-app/nymea-app.pro
+++ b/nymea-app/nymea-app.pro
@@ -124,3 +124,6 @@ BR=$$BRANDING
target.path = /usr/bin
INSTALLS += target
+DISTFILES += \
+ ruletemplates/smartmetertemplates.json
+
diff --git a/nymea-app/ruletemplates.qrc b/nymea-app/ruletemplates.qrc
index ee47f538..24df3a96 100644
--- a/nymea-app/ruletemplates.qrc
+++ b/nymea-app/ruletemplates.qrc
@@ -3,5 +3,6 @@
ruletemplates/buttontemplates.json
ruletemplates/notificationtemplates.json
ruletemplates/accesscontroltemplates.json
+ ruletemplates/smartmetertemplates.json
diff --git a/nymea-app/ruletemplates/smartmetertemplates.json b/nymea-app/ruletemplates/smartmetertemplates.json
new file mode 100644
index 00000000..99485521
--- /dev/null
+++ b/nymea-app/ruletemplates/smartmetertemplates.json
@@ -0,0 +1,84 @@
+{
+ "templates": [
+ {
+ "interfaceName": "extendedsmartmeterproducer",
+ "description": "Charge my car while producing energy.",
+ "ruleNameTemplate": "Smart car charging",
+ "stateEvaluatorTemplate": {
+ "stateDescriptorTemplate": {
+ "interfaceName": "extendedsmartmeterproducer",
+ "interfaceState": "currentPower",
+ "operator": "ValueOperatorGreater",
+ "value": 0,
+ "selectionId": 0
+ }
+ },
+ "ruleActionTemplates": [
+ {
+ "interfaceName": "evcharger",
+ "interfaceAction": "power",
+ "selectionId": 1,
+ "params": [
+ {
+ "name": "power",
+ "value": true
+ }
+ ]
+ }
+ ],
+ "ruleExitActionTemplates": [
+ {
+ "interfaceName": "evcharger",
+ "interfaceAction": "power",
+ "selectionId": 1,
+ "params": [
+ {
+ "name": "power",
+ "value": false
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "interfaceName": "extendedsmartmeterproducer",
+ "description": "Turn on heating while producing energy.",
+ "ruleNameTemplate": "Smart heating",
+ "stateEvaluatorTemplate": {
+ "stateDescriptorTemplate": {
+ "interfaceName": "extendedsmartmeterproducer",
+ "interfaceState": "currentPower",
+ "operator": "ValueOperatorGreater",
+ "value": 0,
+ "selectionId": 0
+ }
+ },
+ "ruleActionTemplates": [
+ {
+ "interfaceName": "heating",
+ "interfaceAction": "power",
+ "selectionId": 1,
+ "params": [
+ {
+ "name": "power",
+ "value": true
+ }
+ ]
+ }
+ ],
+ "ruleExitActionTemplates": [
+ {
+ "interfaceName": "heating",
+ "interfaceAction": "power",
+ "selectionId": 1,
+ "params": [
+ {
+ "name": "power",
+ "value": false
+ }
+ ]
+ }
+ ]
+ }
+ ]
+}
diff --git a/nymea-app/ui/Nymea.qml b/nymea-app/ui/Nymea.qml
index 65116fc8..2ef02af4 100644
--- a/nymea-app/ui/Nymea.qml
+++ b/nymea-app/ui/Nymea.qml
@@ -53,7 +53,7 @@ ApplicationWindow {
rootItem.handleCloseEvent(close)
}
- property var supportedInterfaces: ["light", "weather", "sensor", "media", "garagegate", "awning", "shutter", "blind", "smartmeter", "accesscontrol", "button", "notifications", "inputtrigger", "outputtrigger", "gateway"]
+ property var supportedInterfaces: ["light", "weather", "sensor", "media", "garagegate", "awning", "shutter", "blind", "heating", "smartmeter", "evcharger", "accesscontrol", "button", "notifications", "inputtrigger", "outputtrigger", "gateway"]
function interfaceToString(name) {
switch(name) {
case "light":
@@ -94,7 +94,15 @@ ApplicationWindow {
case "accesscontrol":
return qsTr("Access control");
case "smartmeter":
- return qsTr("Smart meter");
+ case "smartmeterproducer":
+ case "smartmeterconsumer":
+ case "extendedsmartmeterproducer":
+ case "extendedsmartmeterconsumer":
+ return qsTr("Smart meters");
+ case "heating":
+ return qsTr("Heatings");
+ case "evcharger":
+ return qsTr("EV-chargers");
case "uncategorized":
return qsTr("Uncategorized")
default:
@@ -181,6 +189,12 @@ ApplicationWindow {
case "extendedsmartmeterconsumer":
case "extendedsmartmeterproducer":
return Qt.resolvedUrl("images/smartmeter.svg")
+ case "heating":
+ case "extendedheating":
+ return Qt.resolvedUrl("images/radiator.svg")
+ case "evcharger":
+ case "extendedevcharger":
+ return Qt.resolvedUrl("images/ev-charger.svg")
case "connectable":
return Qt.resolvedUrl("images/stock_link.svg")
default:
diff --git a/nymea-app/ui/customviews/GenericTypeGraph.qml b/nymea-app/ui/customviews/GenericTypeGraph.qml
index 964b8827..cca5f4bc 100644
--- a/nymea-app/ui/customviews/GenericTypeGraph.qml
+++ b/nymea-app/ui/customviews/GenericTypeGraph.qml
@@ -13,6 +13,7 @@ Item {
property var device: null
property var stateType: null
+ property int roundTo: 2
readonly property var valueState: device.states.getState(stateType.id)
readonly property var deviceClass: engine.deviceManager.deviceClasses.getDeviceClass(device.deviceClassId);
readonly property bool hasConnectable: deviceClass.interfaces.indexOf("connectable") >= 0
@@ -56,7 +57,7 @@ Item {
Label {
Layout.fillWidth: true
- text: root.valueState.value + " " + root.stateType.unitString
+ text: 1.0 * Math.round(root.valueState.value * Math.pow(10, root.roundTo)) / Math.pow(10, root.roundTo) + " " + root.stateType.unitString
font.pixelSize: app.largeFont
}
diff --git a/nymea-app/ui/devicelistpages/SmartMeterDeviceListPage.qml b/nymea-app/ui/devicelistpages/SmartMeterDeviceListPage.qml
index eceb262f..69aca325 100644
--- a/nymea-app/ui/devicelistpages/SmartMeterDeviceListPage.qml
+++ b/nymea-app/ui/devicelistpages/SmartMeterDeviceListPage.qml
@@ -74,14 +74,26 @@ DeviceListPageBase {
Layout.margins: app.margins
Repeater {
model: ListModel {
- ListElement { interfaceName: "smartmeterproducer"; stateName: "totalEnergyProduced" }
- ListElement { interfaceName: "smartmeterconsumer"; stateName: "totalEnergyConsumed" }
- ListElement { interfaceName: "extendedsmartmeterproducer"; stateName: "currentPower" }
+ Component.onCompleted: {
+ if (itemDelegate.deviceClass.interfaces.indexOf("smartmeterproducer") >= 0) {
+ append( {interfaceName: "smartmeterproducer", stateName: "totalEnergyProduced" })
+ }
+ if (itemDelegate.deviceClass.interfaces.indexOf("smartmeterconsumer") >= 0) {
+ append( {interfaceName: "smartmeterconsumer", stateName: "totalEnergyConsumed" })
+ }
+ var added = false;
+ if (itemDelegate.deviceClass.interfaces.indexOf("extendedsmartmeterproducer") >= 0) {
+ append({interfaceName: "extendedsmartmeterconsumer", stateName: "currentPower"});
+ added = true;
+ }
+ if (!added && itemDelegate.deviceClass.interfaces.indexOf("extendedsmartmeterconsumer") >= 0) {
+ append({interfaceName: "extendedsmartmeterconsumer", stateName: "currentPower"});
+ }
+ }
}
delegate: RowLayout {
id: sensorValueDelegate
- visible: itemDelegate.deviceClass.interfaces.indexOf(model.interfaceName) >= 0
Layout.preferredWidth: contentItem.width / dataGrid.columns
property var stateType: itemDelegate.deviceClass.stateTypes.findByName(model.stateName)
@@ -98,7 +110,7 @@ DeviceListPageBase {
Label {
Layout.fillWidth: true
text: sensorValueDelegate.stateValue
- ? "%1 %2".arg(sensorValueDelegate.stateValue.value).arg(sensorValueDelegate.stateType.unitString)
+ ? "%1 %2".arg(1.0 * Math.round(sensorValueDelegate.stateValue.value * 100000) / 100000).arg(sensorValueDelegate.stateType.unitString)
: ""
elide: Text.ElideRight
verticalAlignment: Text.AlignVCenter
@@ -106,8 +118,7 @@ DeviceListPageBase {
}
}
}
- }
-
+ }
}
onClicked: {
enterPage(index, false)
diff --git a/nymea-app/ui/devicepages/SmartMeterDevicePage.qml b/nymea-app/ui/devicepages/SmartMeterDevicePage.qml
index 961f7dee..c93a10bb 100644
--- a/nymea-app/ui/devicepages/SmartMeterDevicePage.qml
+++ b/nymea-app/ui/devicepages/SmartMeterDevicePage.qml
@@ -38,6 +38,7 @@ DevicePageBase {
stateType: root.deviceClass.stateTypes.findByName(model.stateTypeName)
color: app.interfaceToColor(model.interface)
iconSource: app.interfaceToIcon(model.interface)
+ roundTo: 5
}
}
}
diff --git a/nymea-app/ui/images/ev-charger.svg b/nymea-app/ui/images/ev-charger.svg
new file mode 100644
index 00000000..6cd918c7
--- /dev/null
+++ b/nymea-app/ui/images/ev-charger.svg
@@ -0,0 +1,6537 @@
+
+
\ No newline at end of file
diff --git a/nymea-app/ui/images/radiator.svg b/nymea-app/ui/images/radiator.svg
new file mode 100644
index 00000000..9ff0d994
--- /dev/null
+++ b/nymea-app/ui/images/radiator.svg
@@ -0,0 +1,71 @@
+
+