WIP: drexel und weiss experience
This commit is contained in:
parent
effb5a137f
commit
ae0a3279ec
@ -137,7 +137,7 @@ Connection *NymeaConnection::currentConnection() const
|
||||
void NymeaConnection::sendData(const QByteArray &data)
|
||||
{
|
||||
if (connected()) {
|
||||
qDebug() << "sending data:" << data;
|
||||
// qDebug() << "sending data:" << data;
|
||||
m_currentTransport->sendData(data);
|
||||
} else {
|
||||
qWarning() << "Connection: Not connected. Cannot send.";
|
||||
@ -382,7 +382,7 @@ void NymeaConnection::updateActiveBearers()
|
||||
QList<QNetworkConfiguration> configs = m_networkConfigManager->allConfigurations(QNetworkConfiguration::Active);
|
||||
// qDebug() << "Network configuations:" << configs.count();
|
||||
foreach (const QNetworkConfiguration &config, configs) {
|
||||
qDebug() << "Candidate network config:" << config.name() << config.bearerTypeFamily() << config.bearerTypeName();
|
||||
// qDebug() << "Candidate network config:" << config.name() << config.bearerTypeFamily() << config.bearerTypeName();
|
||||
|
||||
// NOTE: iOS doesn't correctly report bearer types. It'll be Unknown all the time. Let's hardcode it to WiFi for that...
|
||||
#if defined(Q_OS_IOS)
|
||||
|
||||
@ -101,6 +101,20 @@ void DevicesProxy::setFilterTagId(const QString &filterTag)
|
||||
}
|
||||
}
|
||||
|
||||
QString DevicesProxy::filterDeviceClassId() const
|
||||
{
|
||||
return m_filterDeviceClassId;
|
||||
}
|
||||
|
||||
void DevicesProxy::setFilterDeviceClassId(const QString &filterDeviceClassId)
|
||||
{
|
||||
if (m_filterDeviceClassId != filterDeviceClassId) {
|
||||
m_filterDeviceClassId = filterDeviceClassId;
|
||||
emit filterDeviceClassIdChanged();
|
||||
invalidateFilter();
|
||||
}
|
||||
}
|
||||
|
||||
QStringList DevicesProxy::shownInterfaces() const
|
||||
{
|
||||
return m_shownInterfaces;
|
||||
@ -231,6 +245,11 @@ bool DevicesProxy::filterAcceptsRow(int source_row, const QModelIndex &source_pa
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (!m_filterDeviceClassId.isEmpty()) {
|
||||
if (device->deviceClassId() != m_filterDeviceClassId) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
DeviceClass *deviceClass = m_engine->deviceManager()->deviceClasses()->getDeviceClass(device->deviceClassId());
|
||||
if (!m_shownInterfaces.isEmpty()) {
|
||||
bool foundMatch = false;
|
||||
|
||||
@ -38,6 +38,7 @@ class DevicesProxy : public QSortFilterProxyModel
|
||||
Q_PROPERTY(Engine* engine READ engine WRITE setEngine NOTIFY engineChanged)
|
||||
Q_PROPERTY(DevicesProxy *parentProxy READ parentProxy WRITE setParentProxy NOTIFY parentProxyChanged)
|
||||
Q_PROPERTY(QString filterTagId READ filterTagId WRITE setFilterTagId NOTIFY filterTagIdChanged)
|
||||
Q_PROPERTY(QString filterDeviceClassId READ filterDeviceClassId WRITE setFilterDeviceClassId NOTIFY filterDeviceClassIdChanged)
|
||||
Q_PROPERTY(QStringList shownInterfaces READ shownInterfaces WRITE setShownInterfaces NOTIFY shownInterfacesChanged)
|
||||
Q_PROPERTY(QStringList hiddenInterfaces READ hiddenInterfaces WRITE setHiddenInterfaces NOTIFY hiddenInterfacesChanged)
|
||||
Q_PROPERTY(QString nameFilter READ nameFilter WRITE setNameFilter NOTIFY nameFilterChanged)
|
||||
@ -62,6 +63,9 @@ public:
|
||||
QString filterTagId() const;
|
||||
void setFilterTagId(const QString &filterTag);
|
||||
|
||||
QString filterDeviceClassId() const;
|
||||
void setFilterDeviceClassId(const QString &filterDeviceClassId);
|
||||
|
||||
QStringList shownInterfaces() const;
|
||||
void setShownInterfaces(const QStringList &shownInterfaces);
|
||||
|
||||
@ -86,6 +90,7 @@ signals:
|
||||
void engineChanged();
|
||||
void parentProxyChanged();
|
||||
void filterTagIdChanged();
|
||||
void filterDeviceClassIdChanged();
|
||||
void shownInterfacesChanged();
|
||||
void hiddenInterfacesChanged();
|
||||
void nameFilterChanged();
|
||||
@ -100,6 +105,7 @@ private:
|
||||
Engine *m_engine = nullptr;
|
||||
DevicesProxy *m_parentProxy = nullptr;
|
||||
QString m_filterTagId;
|
||||
QString m_filterDeviceClassId;
|
||||
QStringList m_shownInterfaces;
|
||||
QStringList m_hiddenInterfaces;
|
||||
QString m_nameFilter;
|
||||
|
||||
@ -37,7 +37,7 @@ public:
|
||||
StateTypeIdRole
|
||||
};
|
||||
|
||||
explicit States(QObject *parent = 0);
|
||||
explicit States(QObject *parent = nullptr);
|
||||
|
||||
QList<State *> states();
|
||||
|
||||
|
||||
@ -170,5 +170,6 @@
|
||||
<file>ui/images/sensors/presence.svg</file>
|
||||
<file>ui/images/powersocket.svg</file>
|
||||
<file>ui/images/dial.svg</file>
|
||||
<file>ui/images/ventilation.svg</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
|
||||
@ -165,5 +165,6 @@
|
||||
<file>ui/thingconfiguration/ConfigureThingPage.qml</file>
|
||||
<file>ui/connection/CertificateDialog.qml</file>
|
||||
<file>ui/experiences/garagegates/Main.qml</file>
|
||||
<file>ui/experiences/heating/Main.qml</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
|
||||
@ -50,7 +50,6 @@ ApplicationWindow {
|
||||
RootItem {
|
||||
id: rootItem
|
||||
anchors.fill: parent
|
||||
anchors.topMargin: PlatformHelper.getSafeAreaMargins(app)
|
||||
}
|
||||
|
||||
NymeaDiscovery {
|
||||
|
||||
@ -24,8 +24,8 @@ ColumnLayout {
|
||||
}
|
||||
|
||||
readonly property State deviceState: device && stateType ? device.states.getState(stateType.id) : null
|
||||
readonly property double from: dial.stateType.minValue
|
||||
readonly property double to: dial.stateType.maxValue
|
||||
readonly property double from: dial.stateType ? dial.stateType.minValue : 0
|
||||
readonly property double to: dial.stateType ? dial.stateType.maxValue : 100
|
||||
readonly property double anglePerStep: maxAngle / dial.steps
|
||||
readonly property double startAngle: -(dial.steps * dial.anglePerStep) / 2
|
||||
|
||||
@ -90,7 +90,7 @@ ColumnLayout {
|
||||
Label {
|
||||
id: topLabel
|
||||
Layout.fillWidth: true
|
||||
text: rotateMouseArea.currentValue + dial.stateType.unitString
|
||||
text: rotateMouseArea.currentValue + (dial.stateType ? dial.stateType.unitString : "")
|
||||
font.pixelSize: app.largeFont * 1.5
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
visible: dial.showValueLabel && dial.stateType !== null
|
||||
@ -101,7 +101,6 @@ ColumnLayout {
|
||||
Layout.fillWidth: true
|
||||
Layout.fillHeight: true
|
||||
|
||||
|
||||
Item {
|
||||
id: innerDial
|
||||
|
||||
@ -110,7 +109,6 @@ ColumnLayout {
|
||||
anchors.centerIn: parent
|
||||
rotation: dial.startAngle
|
||||
|
||||
|
||||
Rectangle {
|
||||
anchors.fill: rotationButton
|
||||
radius: height / 2
|
||||
@ -167,7 +165,7 @@ ColumnLayout {
|
||||
width: parent.width
|
||||
height: width
|
||||
radius: width / 2
|
||||
color: dial.angleToValue(parent.rotation) <= dial.deviceState.value ? d.poweredColor : d.offColor
|
||||
color: dial.deviceState && dial.angleToValue(parent.rotation) <= dial.deviceState.value ? d.poweredColor : d.offColor
|
||||
Behavior on color { ColorAnimation { duration: 200 } }
|
||||
}
|
||||
}
|
||||
@ -247,8 +245,8 @@ ColumnLayout {
|
||||
dragging = false;
|
||||
}
|
||||
|
||||
readonly property int decimals: dial.stateType.type.toLowerCase() === "int" ? 0 : 1
|
||||
property var currentValue: dial.deviceState.value.toFixed(decimals)
|
||||
readonly property int decimals: dial.stateType && dial.stateType.type.toLowerCase() === "int" ? 0 : 1
|
||||
property var currentValue: dial.deviceState ? dial.deviceState.value.toFixed(decimals) : 0
|
||||
property date lastVibration: new Date()
|
||||
property int startX
|
||||
property int startY
|
||||
|
||||
@ -10,6 +10,7 @@ Item {
|
||||
property alias from: slider.from
|
||||
property alias to: slider.to
|
||||
property alias stepSize: slider.stepSize
|
||||
property alias snapMode: slider.snapMode
|
||||
|
||||
readonly property real rawValue: slider.value
|
||||
|
||||
|
||||
@ -23,6 +23,9 @@ DevicePageBase {
|
||||
readonly property StateType boostStateType: device.deviceClass.stateTypes.findByName("boost")
|
||||
readonly property State boostState: boostStateType ? device.states.getState(boostStateType.id) : null
|
||||
|
||||
Component.onCompleted: {
|
||||
print("d:", root.device, root.targetTemperatureStateType, root.percentageStateType)
|
||||
}
|
||||
|
||||
GridLayout {
|
||||
anchors.fill: parent
|
||||
@ -33,10 +36,11 @@ DevicePageBase {
|
||||
id: dial
|
||||
Layout.fillWidth: true
|
||||
Layout.fillHeight: true
|
||||
visible: root.targetTemperatureStateType || root.percentageStateType
|
||||
// visible: root.targetTemperatureStateType || root.percentageStateType
|
||||
|
||||
device: root.device
|
||||
stateType: root.targetTemperatureStateType ? root.targetTemperatureStateType : root.percentageStateType
|
||||
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
|
||||
385
nymea-app/ui/experiences/heating/Main.qml
Normal file
385
nymea-app/ui/experiences/heating/Main.qml
Normal file
@ -0,0 +1,385 @@
|
||||
import QtQuick 2.3
|
||||
import QtQuick.Layouts 1.2
|
||||
import QtQuick.Controls 2.2
|
||||
import QtQuick.Controls.Material 2.2
|
||||
import "qrc:/ui/components"
|
||||
import Nymea 1.0
|
||||
import QtGraphicalEffects 1.0
|
||||
|
||||
Item {
|
||||
id: root
|
||||
readonly property string title: qsTr("Heating")
|
||||
readonly property string icon: Qt.resolvedUrl("qrc:/ui/images/radiator.svg")
|
||||
|
||||
readonly property Device duwWpDevice: duwWpFilterModel.count > 0 ? duwWpFilterModel.get(0) : null
|
||||
readonly property Device duwLuDevice: duwLuFilterModel.count > 0 ? duwLuFilterModel.get(0) : null
|
||||
|
||||
readonly property State temperatureState: duwWpDevice ? duwWpDevice.states.getState(duwWpDevice.deviceClass.stateTypes.findByName("temperature").id) : null
|
||||
readonly property State targetTemperatureState: duwWpDevice ? duwWpDevice.states.getState(duwWpDevice.deviceClass.stateTypes.findByName("targetTemperature").id) : null
|
||||
readonly property State ventilationModeState: duwLuDevice ? duwLuDevice.states.getState(duwLuDevice.deviceClass.stateTypes.findByName("ventilationMode").id) : null
|
||||
|
||||
function ventilationModeToSliderValue(ventilationMode) {
|
||||
switch (ventilationMode) {
|
||||
case "Automatic":
|
||||
case "Party":
|
||||
return 0
|
||||
case "Manual level 0":
|
||||
return 0;
|
||||
case "Manual level 1":
|
||||
return 1;
|
||||
case "Manual level 2":
|
||||
return 2;
|
||||
case "Manual level 3":
|
||||
return 3;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
function ventilationModeToUiMode(ventilationMode) {
|
||||
switch (ventilationMode) {
|
||||
case "Automatic":
|
||||
return 0
|
||||
case "Party":
|
||||
return 1;
|
||||
case "Manual level 0":
|
||||
case "Manual level 1":
|
||||
case "Manual level 2":
|
||||
case "Manual level 3":
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
|
||||
function uiModeToVentilationMode(uiMode, sliderValue) {
|
||||
switch (uiMode) {
|
||||
case 0:
|
||||
return "Automatic";
|
||||
case 1:
|
||||
return "Party";
|
||||
case 2:
|
||||
return "Manual level " + Math.floor(sliderValue)
|
||||
}
|
||||
}
|
||||
|
||||
function setVentilationMode(uiModeIndex, sliderIndex) {
|
||||
var params =[];
|
||||
var param = {};
|
||||
param["paramTypeId"] = root.ventilationModeState.stateTypeId
|
||||
param["value"] = root.uiModeToVentilationMode(uiModeIndex, sliderIndex)
|
||||
params.push(param)
|
||||
engine.deviceManager.executeAction(root.duwLuDevice.id, root.ventilationModeState.stateTypeId, params)
|
||||
}
|
||||
|
||||
function setTargetTemp(targetTemp) {
|
||||
// We don't want to spam with set value calls so we're going to queue them up and only send one at a time
|
||||
if (d.pendingCallId != -1) {
|
||||
d.queuedTargetTemp = targetTemp;
|
||||
d.setTempPending = true;
|
||||
return;
|
||||
}
|
||||
var params = []
|
||||
var param = {}
|
||||
param["paramTypeId"] = root.targetTemperatureState.stateTypeId
|
||||
param["value"] = targetTemp
|
||||
params.push(param)
|
||||
d.pendingCallId = engine.deviceManager.executeAction(root.duwWpDevice.id, root.targetTemperatureState.stateTypeId, params)
|
||||
d.setTempPending = false;
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: engine.deviceManager
|
||||
onExecuteActionReply: {
|
||||
print("executeActionReply:", params["id"])
|
||||
if (params["id"] === d.pendingCallId) {
|
||||
d.pendingCallId = -1;
|
||||
if (d.setTempPending) {
|
||||
setTargetTemp(d.queuedTargetTemp)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QtObject {
|
||||
id: d
|
||||
property int pendingCallId: -1
|
||||
property bool setTempPending: false
|
||||
property real queuedTargetTemp: 0
|
||||
}
|
||||
|
||||
DevicesProxy {
|
||||
id: duwWpFilterModel
|
||||
engine: _engine
|
||||
filterDeviceClassId: "e548f962-92db-4110-8279-10fbcde35f93"
|
||||
}
|
||||
|
||||
DevicesProxy {
|
||||
id: duwLuFilterModel
|
||||
engine: _engine
|
||||
filterDeviceClassId: "0de8e21e-392a-4790-a78a-b1a7eaa7571b"
|
||||
}
|
||||
|
||||
EmptyViewPlaceholder {
|
||||
anchors.centerIn: parent
|
||||
width: parent.width - app.margins * 2
|
||||
text: qsTr("There is no drexel und weiss heating system set up yet.")
|
||||
imageSource: "qrc:/ui/images/radiator.svg"
|
||||
buttonText: qsTr("Set up now")
|
||||
visible: duwWpFilterModel.count === 0 && !engine.deviceManager.fetchingData
|
||||
}
|
||||
|
||||
|
||||
Item {
|
||||
id: mainView
|
||||
anchors.fill: parent
|
||||
visible: root.duwWpDevice !== null
|
||||
|
||||
ColumnLayout {
|
||||
anchors.fill: parent
|
||||
anchors.margins: app.margins
|
||||
|
||||
RowLayout {
|
||||
spacing: app.margins
|
||||
ColorIcon {
|
||||
Layout.preferredHeight: app.iconSize
|
||||
Layout.preferredWidth: app.iconSize
|
||||
name: "qrc:/ui/images/weathericons/wind.svg"
|
||||
color: app.accentColor
|
||||
}
|
||||
Led {
|
||||
}
|
||||
}
|
||||
|
||||
Label {
|
||||
text: qsTr("Current temperature")
|
||||
font.pixelSize: app.smallFont
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
ColorIcon {
|
||||
Layout.preferredHeight: app.iconSize
|
||||
Layout.preferredWidth: app.iconSize
|
||||
name: "qrc:/ui/images/sensors/temperature.svg"
|
||||
color: app.accentColor
|
||||
}
|
||||
Label {
|
||||
text: root.temperatureState ? root.temperatureState.value.toFixed(1) + "°C" : "N/A"
|
||||
Layout.fillWidth: true
|
||||
font.pixelSize: app.largeFont * 2
|
||||
}
|
||||
}
|
||||
|
||||
Item {
|
||||
Layout.preferredHeight: app.margins * 2
|
||||
Layout.fillWidth: true
|
||||
}
|
||||
|
||||
Label {
|
||||
text: qsTr("Temperature, °C")
|
||||
font.pixelSize: app.largeFont
|
||||
}
|
||||
Label {
|
||||
text: (d.pendingCallId !== -1 || d.setTempPending) ? d.queuedTargetTemp.toFixed(1) :
|
||||
root.targetTemperatureState ? root.targetTemperatureState.value.toFixed(1) : "N/A"
|
||||
font.pixelSize: app.largeFont * 4
|
||||
}
|
||||
|
||||
Item {
|
||||
Layout.preferredHeight: app.margins * 2
|
||||
Layout.fillWidth: true
|
||||
}
|
||||
ColorIcon {
|
||||
Layout.preferredHeight: app.iconSize * 1.5
|
||||
Layout.preferredWidth: height
|
||||
Layout.leftMargin: width
|
||||
color: app.accentColor
|
||||
name: "qrc:/ui/images/share.svg"
|
||||
}
|
||||
Label {
|
||||
text: qsTr("Automate this thing")
|
||||
color: app.accentColor
|
||||
font.pixelSize: app.smallFont
|
||||
}
|
||||
|
||||
Item {
|
||||
Layout.fillWidth: true
|
||||
Layout.fillHeight: true
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
Layout.leftMargin: parent.width * .05
|
||||
Layout.rightMargin: parent.width * .2
|
||||
spacing: app.margins
|
||||
ColorIcon {
|
||||
Layout.preferredHeight: app.iconSize
|
||||
Layout.preferredWidth: app.iconSize
|
||||
color: app.accentColor
|
||||
name: "qrc:/ui/images/ventilation.svg"
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
Layout.fillWidth: true
|
||||
Layout.maximumHeight: app.iconSize
|
||||
spacing: 0
|
||||
|
||||
Repeater {
|
||||
model: ListModel {
|
||||
ListElement { text: qsTr("Auto") }
|
||||
ListElement { text: qsTr("Party") }
|
||||
ListElement { text: qsTr("Manual") }
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
Layout.fillWidth: true
|
||||
Layout.fillHeight: true
|
||||
border.width: 1
|
||||
border.color: app.accentColor
|
||||
color: root.ventilationModeState && root.ventilationModeToUiMode(root.ventilationModeState.value) === index ? app.accentColor : "transparent"
|
||||
Label {
|
||||
anchors.centerIn: parent
|
||||
text: model.text
|
||||
font.pixelSize: app.smallFont
|
||||
}
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
onClicked: {
|
||||
root.setVentilationMode(index, ventilationSlider.value)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Slider {
|
||||
id: ventilationSlider
|
||||
Layout.fillWidth: true
|
||||
Layout.leftMargin: parent.width * .05
|
||||
Layout.rightMargin: parent.width * .05
|
||||
from: 0
|
||||
to: 4
|
||||
stepSize: 1
|
||||
live: false
|
||||
snapMode: Slider.SnapAlways
|
||||
enabled: root.ventilationModeState && root.ventilationModeToUiMode(root.ventilationModeState.value) === 2
|
||||
opacity: enabled ? 1 : .2
|
||||
value: root.ventilationModeState ? root.ventilationModeToSliderValue(root.ventilationModeState.value) : 0
|
||||
onMoved: root.setVentilationMode(2, ventilationSlider.value)
|
||||
|
||||
}
|
||||
|
||||
ProgressButton {
|
||||
imageSource: "qrc:/ui/images/system-shutdown.svg"
|
||||
Layout.preferredHeight: app.iconSize * 1.5
|
||||
Layout.preferredWidth: height
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
}
|
||||
|
||||
Label {
|
||||
text: qsTr("Hold to turn off")
|
||||
font.pixelSize: app.smallFont
|
||||
Layout.fillWidth: true
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
}
|
||||
}
|
||||
|
||||
Item {
|
||||
height: parent.height * .85
|
||||
width: height
|
||||
anchors.left: parent.right
|
||||
anchors.leftMargin: -width * .25
|
||||
anchors.top: parent.top
|
||||
anchors.topMargin: -height * .05
|
||||
z: -1
|
||||
|
||||
Rectangle {
|
||||
id: outerRadius
|
||||
anchors.fill: parent
|
||||
radius: width / 2
|
||||
border.width: 3
|
||||
color: "transparent"
|
||||
border.color: app.accentColor
|
||||
}
|
||||
|
||||
Glow {
|
||||
anchors.fill: parent
|
||||
source: outerRadius
|
||||
// color: "#f45b69"
|
||||
color: Qt.rgba(app.accentColor.r, app.accentColor.g, app.accentColor.b, .5)
|
||||
radius: 8
|
||||
samples: 17
|
||||
spread: 0.5
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: innerRadius
|
||||
anchors.fill: parent
|
||||
anchors.margins: parent.width * .02
|
||||
radius: width / 2
|
||||
border.width: 2
|
||||
color: "transparent"
|
||||
border.color: app.accentColor
|
||||
|
||||
Repeater {
|
||||
id: ticksRepeater
|
||||
model: 180
|
||||
|
||||
Item {
|
||||
height: isBold ? 3 : 2
|
||||
width: parent.width - 2
|
||||
anchors.centerIn: parent
|
||||
rotation: index * 360 / ticksRepeater.count
|
||||
readonly property int isBold: index % 10 === 0
|
||||
// Rectangle { anchors.fill: parent; color: "blue" }
|
||||
|
||||
Rectangle { height: parent.height; width: parent.isBold ? 20 : 10; color: app.accentColor }
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
|
||||
property real startAnglePress
|
||||
property real startAngleDial
|
||||
property real startTemp
|
||||
|
||||
onPressed: {
|
||||
startAnglePress = calculateAngle(mouseX, mouseY)
|
||||
startAngleDial = innerRadius.rotation
|
||||
startTemp = root.targetTemperatureState.value
|
||||
|
||||
print("angle:", calculateAngle(mouseX, mouseY))
|
||||
}
|
||||
|
||||
onPositionChanged: {
|
||||
var currentAngle = calculateAngle(mouseX, mouseY)
|
||||
var angleDiff = currentAngle - startAnglePress
|
||||
|
||||
var tempDiff = Math.round(angleDiff / 2) / 10
|
||||
var newTemp = startTemp + tempDiff
|
||||
|
||||
innerRadius.rotation = startAngleDial + angleDiff
|
||||
|
||||
print("new degree value", newTemp)
|
||||
root.setTargetTemp(newTemp);
|
||||
}
|
||||
|
||||
function calculateAngle(mouseX, mouseY) {
|
||||
// transform coords to center of dial
|
||||
mouseX -= width / 2
|
||||
mouseY -= height / 2
|
||||
|
||||
var rad = Math.atan(mouseY / mouseX);
|
||||
var angle = rad * 180 / Math.PI
|
||||
|
||||
angle += 90;
|
||||
|
||||
if (mouseX < 0 && mouseY >= 0) angle = 180 + angle;
|
||||
if (mouseX < 0 && mouseY < 0) angle = 180 + angle;
|
||||
|
||||
return angle;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
29
nymea-app/ui/images/ventilation.svg
Normal file
29
nymea-app/ui/images/ventilation.svg
Normal file
@ -0,0 +1,29 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 22.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="svg4874" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 96 96" style="enable-background:new 0 0 96 96;" xml:space="preserve">
|
||||
<style type="text/css">
|
||||
.st0{fill:#808080;}
|
||||
</style>
|
||||
<title>settings</title>
|
||||
<path class="st0" d="M56.4,79.1c-1.5,0-3-0.3-4.4-0.9c-3.2-1.4-4.8-4.4-4.4-8.2c0.4-2.6,1.5-5.1,3.2-7.2c1.3-1.9,2.3-3.4,2.2-5.5
|
||||
c-1.5,0.8-3.2,1.2-4.9,1.2c-1.5,3.1-3.7,5.8-6.4,7.9c-2.6,2-11.7,7.8-20.7-0.5c-3.7-3.4-5.1-9.7-3.1-14.1c1.4-3.2,4.4-4.8,8.2-4.4
|
||||
c2.6,0.4,5.1,1.5,7.2,3.2c1.9,1.3,3.4,2.3,5.4,2.2c-0.8-1.5-1.2-3.2-1.2-4.9c-3.1-1.5-5.8-3.7-7.9-6.4c-2-2.6-7.8-11.7,0.5-20.7
|
||||
c3.4-3.7,9.7-5.1,14.1-3.1c3.2,1.4,4.8,4.4,4.4,8.2c-0.4,2.6-1.5,5.1-3.2,7.2c-1.3,1.9-2.3,3.4-2.2,5.5c1.9-1,4.1-1.4,6.3-1.1
|
||||
c1,0.1,1.6,1,1.5,2c-0.1,1-1,1.6-2,1.5l0,0c-1.5-0.2-3.1,0.1-4.4,0.9c-0.5,0.3-0.9,0.6-1.3,1c-0.7,0.7-1.8,0.6-2.5-0.1
|
||||
c-0.2-0.2-0.3-0.4-0.4-0.6c-0.2-0.6-0.4-1.2-0.5-1.8c-0.9-4.1,0.9-6.8,2.6-9.2c1.2-1.7,2.3-3.4,2.6-5.6c0.2-2.3-0.5-3.8-2.3-4.6
|
||||
c-3-1.3-7.7-0.3-10.1,2.3c-6.2,6.8-2.2,13.5-0.3,16.2c1.9,2.6,4.6,4.6,7.6,5.8c0.8,0.3,1.2,1.1,1.1,1.9c-0.2,1.5,0.1,3.1,0.9,4.4
|
||||
c0.3,0.5,0.6,0.9,1,1.3c0.7,0.7,0.6,1.8-0.1,2.5c-0.2,0.2-0.4,0.3-0.6,0.4c-0.6,0.2-1.2,0.4-1.8,0.5c-4.1,0.9-6.8-0.9-9.2-2.6
|
||||
c-1.7-1.2-3.4-2.3-5.6-2.6c-2.3-0.2-3.8,0.5-4.6,2.3c-1.3,3-0.3,7.7,2.3,10.1c6.8,6.2,13.6,2.2,16.2,0.3c2.6-1.9,4.6-4.6,5.8-7.6
|
||||
c0.3-0.8,1.1-1.2,1.9-1.1c1.5,0.2,3.1-0.1,4.4-0.9c0.5-0.3,0.9-0.6,1.3-1c0.7-0.7,1.8-0.6,2.5,0.1c0.2,0.2,0.3,0.4,0.4,0.6
|
||||
c0.2,0.6,0.4,1.2,0.5,1.8c0.9,4.1-0.9,6.8-2.6,9.1c-1.2,1.7-2.3,3.4-2.6,5.6c-0.2,2.3,0.5,3.8,2.3,4.6c3,1.3,7.7,0.3,10.1-2.3
|
||||
c6.2-6.8,2.2-13.6,0.3-16.2c-1.9-2.6-4.6-4.6-7.6-5.8c-0.8-0.3-1.2-1.1-1.1-1.9c0.2-1.5-0.1-3.1-0.9-4.4c-0.3-0.5-0.6-0.9-1-1.3
|
||||
c-0.7-0.7-0.6-1.8,0.1-2.5c0.2-0.2,0.4-0.3,0.6-0.4c0.6-0.2,1.2-0.4,1.8-0.5c4.1-0.9,6.8,0.9,9.1,2.6c1.7,1.2,3.4,2.3,5.6,2.6
|
||||
c2.3,0.2,3.8-0.5,4.6-2.3c1.3-3,0.3-7.7-2.3-10.1c-6.8-6.2-13.6-2.2-16.2-0.3c-1,0.8-1.9,1.7-2.8,2.6c-0.6,0.7-1.7,0.8-2.5,0.2
|
||||
c-0.7-0.6-0.8-1.7-0.2-2.5c1-1.1,2.1-2.2,3.3-3.1c2.6-2,11.7-7.8,20.7,0.5c3.7,3.4,5.1,9.7,3.1,14.1c-1.4,3.2-4.4,4.8-8.2,4.4
|
||||
c-2.6-0.4-5.1-1.5-7.2-3.2c-1.9-1.3-3.4-2.3-5.5-2.2c0.8,1.5,1.2,3.2,1.2,4.9c3.1,1.5,5.8,3.7,7.9,6.4c2,2.6,7.8,11.7-0.5,20.7
|
||||
C63.5,77.7,60,79.1,56.4,79.1z"/>
|
||||
<path class="st0" d="M48,89.8C24.9,89.8,6.2,71.1,6.2,48C6.2,24.9,24.9,6.2,48,6.2c23.1,0,41.8,18.7,41.8,41.8
|
||||
C89.8,71.1,71.1,89.8,48,89.8z M48,9.7C26.8,9.7,9.7,26.8,9.7,48S26.8,86.3,48,86.3S86.3,69.2,86.3,48c0,0,0,0,0,0
|
||||
C86.3,26.8,69.2,9.7,48,9.7z"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.6 KiB |
Reference in New Issue
Block a user