implement presence and daylight sensor interface support

This commit is contained in:
Michael Zanetti 2018-12-20 22:26:50 +01:00
parent 84d98ffc93
commit dcccf71205
10 changed files with 346 additions and 20 deletions

View File

@ -242,6 +242,7 @@ void DeviceManager::getConfiguredDevicesResponse(const QVariantMap &params)
// qDebug() << "Set device state value:" << device->stateValue(stateTypeId) << value;
}
devices()->addDevice(device);
qDebug() << "*** Added device:" << endl << device;
}
}
m_fetchingData = false;

View File

@ -134,3 +134,19 @@ void Device::setStateValue(const QUuid &stateTypeId, const QVariant &value)
}
}
}
QDebug operator<<(QDebug &dbg, Device *device)
{
dbg.nospace() << "Device: " << device->name() << " (" << device->id().toString() << ") Class:" << device->deviceClass()->name() << " (" << device->deviceClassId().toString() << ")" << endl;
for (int i = 0; i < device->params()->rowCount(); i++) {
Param *p = device->params()->get(i);
ParamType *pt = device->deviceClass()->paramTypes()->getParamType(p->paramTypeId());
dbg << " Param " << i << ": " << pt->id().toString() << ": " << pt->name() << " = " << p->value() << endl;
}
for (int i = 0; i < device->deviceClass()->stateTypes()->rowCount(); i++) {
StateType *st = device->deviceClass()->stateTypes()->get(i);
State *s = device->states()->getState(st->id());
dbg << " State " << i << ": " << st->id() << ": " << st->name() << " = " << s->value() << endl;
}
return dbg;
}

View File

@ -87,4 +87,6 @@ signals:
};
QDebug operator<<(QDebug &dbg, Device* device);
#endif // DEVICE_H

View File

@ -167,5 +167,6 @@
<file>ui/images/media-playlist.svg</file>
<file>ui/images/stock_music.svg</file>
<file>ui/images/stock_video.svg</file>
<file>ui/images/sensors/presence.svg</file>
</qresource>
</RCC>

View File

@ -144,5 +144,6 @@
<file>ui/system/MqttBrokerSettingsPage.qml</file>
<file>ui/system/ServerConfigurationDialog.qml</file>
<file>ui/system/MqttPolicyPage.qml</file>
<file>ui/devicepages/BoolSensorDevicePage.qml</file>
</qresource>
</RCC>

View File

@ -148,6 +148,10 @@ ApplicationWindow {
return Qt.resolvedUrl("images/sensors/noise.svg");
case "co2sensor":
return Qt.resolvedUrl("images/sensors/co2.svg")
case "daylightsensor":
return Qt.resolvedUrl("images/sensors/light.svg")
case "presencesensor":
return Qt.resolvedUrl("images/sensors/presence.svg")
case "media":
case "mediacontroller":
return Qt.resolvedUrl("images/mediaplayer-app-symbolic.svg")
@ -216,6 +220,8 @@ ApplicationWindow {
"pressuresensor": "grey",
"noisesensor": "darkviolet",
"co2sensor": "turquoise",
"daylightsensor": "gold",
"presencesensor": "darkblue",
"smartmeterproducer": "lightgreen",
"smartmeterconsumer": "orange",
"extendedsmartmeterproducer": "blue",

View File

@ -82,6 +82,8 @@ DeviceListPageBase {
ListElement { interfaceName: "conductivitysensor"; stateName: "conductivity" }
ListElement { interfaceName: "noisesensor"; stateName: "noise" }
ListElement { interfaceName: "co2sensor"; stateName: "co2" }
ListElement { interfaceName: "daylightsensor"; stateName: "daylight" }
ListElement { interfaceName: "presencesensor"; stateName: "isPresent" }
}
delegate: RowLayout {
@ -89,8 +91,8 @@ DeviceListPageBase {
visible: itemDelegate.deviceClass.interfaces.indexOf(model.interfaceName) >= 0
Layout.preferredWidth: contentItem.width / dataGrid.columns
property var stateType: itemDelegate.deviceClass.stateTypes.findByName(model.stateName)
property var stateValue: stateType ? itemDelegate.device.states.getState(stateType.id) : null
property StateType stateType: itemDelegate.deviceClass.stateTypes.findByName(model.stateName)
property State stateValue: stateType ? itemDelegate.device.states.getState(stateType.id) : null
ColorIcon {
Layout.preferredHeight: app.iconSize * .8
@ -102,17 +104,22 @@ DeviceListPageBase {
Label {
Layout.fillWidth: true
text: sensorValueDelegate.stateValue
? "%1 %2".arg(Math.round(sensorValueDelegate.stateValue.value * 100) / 100).arg(sensorValueDelegate.stateType.unitString)
: ""
text: sensorValueDelegate.stateType && sensorValueDelegate.stateType.type.toLowerCase() === "bool"
? sensorValueDelegate.stateType.displayName
: sensorValueDelegate.stateValue
? "%1 %2".arg(Math.round(sensorValueDelegate.stateValue.value * 100) / 100).arg(sensorValueDelegate.stateType.unitString)
: ""
elide: Text.ElideRight
verticalAlignment: Text.AlignVCenter
font.pixelSize: app.smallFont
}
Led {
visible: sensorValueDelegate.stateType && sensorValueDelegate.stateType.type.toLowerCase() == "bool"
on: visible && sensorValueDelegate.stateValue.value === true
}
}
}
}
}
}
onClicked: {
enterPage(index, false)

View File

@ -0,0 +1,40 @@
import QtQuick 2.5
import QtQuick.Controls 2.1
import QtQuick.Layouts 1.1
import Nymea 1.0
import "../components"
import "../customviews"
Item {
GridLayout {
anchors.fill: parent
anchors.margins: app.margins
columns: app.landscape ? 2 : 1
rowSpacing: app.margins
columnSpacing: app.margins
Layout.alignment: Qt.AlignCenter
Item {
Layout.preferredWidth: Math.max(app.iconSize * 4, parent.width / 5)
Layout.preferredHeight: width
Layout.topMargin: app.margins
Layout.bottomMargin: app.landscape ? app.margins : 0
Layout.alignment: Qt.AlignCenter
Layout.rowSpan: app.landscape ? 4 : 1
Layout.fillHeight: true
ColorIcon {
anchors.fill: parent
anchors.margins: app.margins * 1.5
name: root.powerState.value === true ? "../images/light-on.svg" : "../images/light-off.svg"
color: root.powerState.value === true ? app.accentColor : keyColor
}
}
}
}

View File

@ -6,10 +6,12 @@ import "../components"
import "../customviews"
ListView {
id: listView
anchors { fill: parent }
interactive: contentHeight > height
model: ListModel {
Component.onCompleted: {
var supportedInterfaces = ["temperaturesensor", "humiditysensor", "pressuresensor", "moisturesensor", "lightsensor", "conductivitysensor", "noisesensor", "co2sensor"]
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) {
@ -18,20 +20,107 @@ ListView {
}
}
}
delegate: GenericTypeGraph {
delegate: Loader {
id: loader
width: parent.width
device: root.device
stateType: root.deviceClass.stateTypes.findByName(stateTypeName)
color: app.interfaceToColor(modelData)
iconSource: app.interfaceToIcon(modelData)
implicitHeight: width * .6
property string stateTypeName: {
switch (modelData) {
case "lightsensor":
return "lightIntensity";
default:
return modelData.replace("sensor", "");
property StateType stateType: root.deviceClass.stateTypes.findByName(interfaceStateMap[modelData])
property string interfaceName: modelData
sourceComponent: stateType && stateType.type.toLowerCase() === "bool" ? boolComponent : graphComponent
property var interfaceStateMap: {
"temperaturesensor": "temperature",
"humiditysensor": "humidity",
"pressuresensor": "pressure",
"moisturesensor": "moisture",
"lightsensor": "lightIntensity",
"conductivitysensor": "conductivity",
"noisesensor": "noise",
"co2sensor": "co2",
"presencesensor": "isPresent",
"daylightsensor": "daylight"
}
}
Component {
id: graphComponent
GenericTypeGraph {
device: root.device
color: app.interfaceToColor(interfaceName)
iconSource: app.interfaceToIcon(interfaceName)
implicitHeight: width * .6
property string interfaceName: parent.interfaceName
stateType: parent.stateType
}
}
Component {
id: boolComponent
GridLayout {
id: boolView
property string interfaceName: parent.interfaceName
property StateType stateType: parent.stateType
height: listView.height
columns: app.landscape ? 2 : 1
Item {
Layout.fillWidth: true
Layout.fillHeight: true
Layout.rowSpan: 3
ColorIcon {
anchors.centerIn: parent
height: app.iconSize * 4
width: height
name: app.interfaceToIcon(boolView.interfaceName)
color: device.states.getState(boolView.stateType.id).value === true ? app.interfaceToColor(boolView.interfaceName) : keyColor
}
}
RowLayout {
Layout.fillWidth: false
Layout.alignment: Qt.AlignHCenter
property StateType lastSeenStateType: root.deviceClass.stateTypes.findByName("lastSeenTime")
property State lastSeenState: lastSeenStateType ? root.device.states.getState(lastSeenStateType.id) : null
visible: lastSeenStateType !== null
Label {
text: qsTr("Last seen:")
font.bold: true
}
Label {
text: Qt.formatDateTime(new Date(parent.lastSeenState.value))
}
}
RowLayout {
Layout.fillWidth: false
Layout.alignment: Qt.AlignHCenter
property StateType sunriseStateType: root.deviceClass.stateTypes.findByName("sunriseTime")
property State sunriseState: sunriseStateType ? root.device.states.getState(sunriseStateType.id) : null
visible: sunriseStateType !== null
Label {
text: qsTr("Sunrise:")
font.bold: true
}
Label {
text: parent.sunriseStateType ? Qt.formatDateTime(new Date(parent.sunriseState.value)) : ""
}
}
RowLayout {
Layout.fillWidth: false
Layout.alignment: Qt.AlignHCenter
property StateType sunsetStateType: root.deviceClass.stateTypes.findByName("sunsetTime")
property State sunsetState: sunsetStateType ? root.device.states.getState(sunsetStateType.id) : null
visible: sunsetStateType !== null
Label {
text: qsTr("Sunset:")
font.bold: true
}
Label {
text: parent.sunsetStateType ? Qt.formatDateTime(new Date(parent.sunsetState.value)) : ""
}
}
Item {
Layout.fillHeight: true
Layout.fillWidth: true
}
}
}

View File

@ -0,0 +1,163 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="96"
height="96"
id="svg4874"
version="1.1"
inkscape:version="0.91+devel r"
viewBox="0 0 96 96.000001"
sodipodi:docname="location.svg">
<defs
id="defs4876" />
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="5.7646075"
inkscape:cx="42.448473"
inkscape:cy="30.951139"
inkscape:document-units="px"
inkscape:current-layer="g4780"
showgrid="false"
showborder="true"
fit-margin-top="0"
fit-margin-left="0"
fit-margin-right="0"
fit-margin-bottom="0"
inkscape:snap-bbox="true"
inkscape:bbox-paths="true"
inkscape:bbox-nodes="true"
inkscape:snap-bbox-edge-midpoints="true"
inkscape:snap-bbox-midpoints="true"
inkscape:object-paths="true"
inkscape:snap-intersection-paths="true"
inkscape:object-nodes="true"
inkscape:snap-smooth-nodes="true"
inkscape:snap-midpoints="true"
inkscape:snap-object-midpoints="true"
inkscape:snap-center="true"
showguides="true"
inkscape:guide-bbox="true">
<inkscape:grid
type="xygrid"
id="grid5451"
empspacing="8" />
<sodipodi:guide
orientation="1,0"
position="8,-8.0000001"
id="guide4063" />
<sodipodi:guide
orientation="1,0"
position="4,-8.0000001"
id="guide4065" />
<sodipodi:guide
orientation="0,1"
position="-8,88.000001"
id="guide4067" />
<sodipodi:guide
orientation="0,1"
position="-8,92.000001"
id="guide4069" />
<sodipodi:guide
orientation="0,1"
position="104,4"
id="guide4071" />
<sodipodi:guide
orientation="0,1"
position="-5,8.0000001"
id="guide4073" />
<sodipodi:guide
orientation="1,0"
position="92,-8.0000001"
id="guide4075" />
<sodipodi:guide
orientation="1,0"
position="88,-8.0000001"
id="guide4077" />
<sodipodi:guide
orientation="0,1"
position="-8,84.000001"
id="guide4074" />
<sodipodi:guide
orientation="1,0"
position="12,-8.0000001"
id="guide4076" />
<sodipodi:guide
orientation="0,1"
position="-5,12"
id="guide4078" />
<sodipodi:guide
orientation="1,0"
position="84,-9.0000001"
id="guide4080" />
<sodipodi:guide
position="48,-8.0000001"
orientation="1,0"
id="guide4170" />
<sodipodi:guide
position="-8,48"
orientation="0,1"
id="guide4172" />
</sodipodi:namedview>
<metadata
id="metadata4879">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(67.857146,-78.50504)">
<g
transform="matrix(0,-1,-1,0,373.50506,516.50504)"
id="g4845"
style="display:inline">
<g
inkscape:export-ydpi="90"
inkscape:export-xdpi="90"
inkscape:export-filename="next01.png"
transform="matrix(-0.9996045,0,0,1,575.94296,-611.00001)"
id="g4778"
inkscape:label="Layer 1">
<g
transform="matrix(-1,0,0,1,575.99999,611)"
id="g4780"
style="display:inline">
<path
style="color:#000000;display:inline;overflow:visible;visibility:visible;opacity:1;fill:#808080;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2.99940658;marker:none;enable-background:accumulate"
d="M 48 0 A 25.999994 25.999998 0 0 0 22 26 A 25.999994 25.999998 0 0 0 23.650391 35.066406 A 25.999994 26.000001 0 0 1 23.210938 33.818359 C 27.972357 48.1029 37.544257 75.297989 47.998047 96 C 47.999047 95.999 47.99936 95.997093 48 95.996094 L 48.001953 96 C 58.455743 75.297988 68.027643 48.102901 72.789062 33.818359 A 25.999994 25.999998 0 0 0 74 26 A 25.999994 25.999998 0 0 0 48 0 z M 48 4 A 22.000006 22.000008 0 0 1 70 26 A 22.000006 22.000008 0 0 1 48 48 A 22.000006 22.000008 0 0 1 26 26 A 22.000006 22.000008 0 0 1 48 4 z "
transform="matrix(0,-1,-1.0003957,0,438.00245,441.36222)"
id="path4176" />
<rect
style="color:#000000;display:inline;overflow:visible;visibility:visible;fill:none;stroke:none;stroke-width:4;marker:none;enable-background:accumulate"
id="rect4782"
width="96.037987"
height="96"
x="-438.00244"
y="345.36221"
transform="scale(-1,1)" />
</g>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 5.2 KiB