659 lines
28 KiB
QML
659 lines
28 KiB
QML
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
|
*
|
|
* Copyright 2013 - 2022, nymea GmbH
|
|
* Contact: contact@nymea.io
|
|
*
|
|
* This file is part of nymea.
|
|
* This project including source code and documentation is protected by
|
|
* copyright law, and remains the property of nymea GmbH. All rights, including
|
|
* reproduction, publication, editing and translation, are reserved. The use of
|
|
* this project is subject to the terms of a license agreement to be concluded
|
|
* with nymea GmbH in accordance with the terms of use of nymea GmbH, available
|
|
* under https://nymea.io/license
|
|
*
|
|
* GNU General Public License Usage
|
|
* Alternatively, this project may be redistributed and/or modified under the
|
|
* terms of the GNU General Public License as published by the Free Software
|
|
* Foundation, GNU version 3. This project is distributed in the hope that it
|
|
* will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
|
|
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
|
|
* Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License along with
|
|
* this project. If not, see <https://www.gnu.org/licenses/>.
|
|
*
|
|
* For any further details and any questions please contact us under
|
|
* contact@nymea.io or see our FAQ/Licensing Information on
|
|
* https://nymea.io/license/faq
|
|
*
|
|
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
|
|
|
import QtQuick 2.8
|
|
import QtQuick.Controls 2.2
|
|
import QtQuick.Controls.Material 2.1
|
|
import QtQuick.Layouts 1.3
|
|
import "qrc:/ui/components"
|
|
import Nymea 1.0
|
|
import NymeaApp.Utils 1.0
|
|
|
|
SettingsPageBase {
|
|
id: root
|
|
|
|
property ZigbeeManager zigbeeManager: null
|
|
property ZigbeeNetwork network: null
|
|
property ZigbeeNode node: null
|
|
readonly property ZigbeeNode coordinatorNode: root.network.nodes.getNodeByNetworkAddress(0)
|
|
|
|
header: NymeaHeader {
|
|
text: qsTr("ZigBee node info")
|
|
backButtonVisible: true
|
|
onBackPressed: pageStack.pop()
|
|
|
|
HeaderButton {
|
|
imageSource: "/ui/images/delete.svg"
|
|
text: qsTr("Remove node")
|
|
onClicked: {
|
|
var popup = removeZigbeeNodeDialogComponent.createObject(app)
|
|
popup.open()
|
|
}
|
|
}
|
|
}
|
|
|
|
busy: d.pendingCommandId != -1
|
|
|
|
QtObject {
|
|
id: d
|
|
property int pendingCommandId: -1
|
|
function removeNode(networkUuid, ieeeAddress) {
|
|
d.pendingCommandId = root.zigbeeManager.removeNode(networkUuid, ieeeAddress)
|
|
}
|
|
|
|
onPendingCommandIdChanged: {
|
|
print("pendingCommandId changed", pendingCommandId, wakeupDialog)
|
|
if (pendingCommandId == -1 && wakeupDialog != null) {
|
|
wakeupDialog.close();
|
|
wakeupDialog.destroy();
|
|
wakeupDialog = null
|
|
}
|
|
}
|
|
|
|
property var wakeupDialog: null
|
|
}
|
|
|
|
Connections {
|
|
target: root.zigbeeManager
|
|
onCreateBindingReply: {
|
|
print("**** create binding reply", error)
|
|
if (commandId == d.pendingCommandId) {
|
|
d.pendingCommandId = -1
|
|
var props = {};
|
|
switch (error) {
|
|
case ZigbeeManager.ZigbeeErrorNoError:
|
|
return;
|
|
case ZigbeeManager.ZigbeeErrorNetworkError:
|
|
props.text = qsTr("An error happened in the ZigBee network when creating the binding.");
|
|
break;
|
|
case ZigbeeManager.ZigbeeErrorTimeoutError:
|
|
props.text = qsTr("The ZigBee device did not respond. Please try again.");
|
|
break;
|
|
default:
|
|
props.error = error;
|
|
}
|
|
var comp = Qt.createComponent("/ui/components/ErrorDialog.qml")
|
|
var popup = comp.createObject(app, props)
|
|
popup.open();
|
|
}
|
|
}
|
|
onRemoveBindingReply: {
|
|
if (commandId == d.pendingCommandId) {
|
|
d.pendingCommandId = -1
|
|
|
|
var props = {};
|
|
switch (error) {
|
|
case ZigbeeManager.ZigbeeErrorNoError:
|
|
return;
|
|
case ZigbeeManager.ZigbeeErrorNetworkError:
|
|
props.text = qsTr("An error happened in the ZigBee network when removing the binding.");
|
|
break;
|
|
case ZigbeeManager.ZigbeeErrorTimeoutError:
|
|
props.text = qsTr("The ZigBee device did not respond. Please try again.");
|
|
break;
|
|
default:
|
|
props.error = error;
|
|
}
|
|
var comp = Qt.createComponent("/ui/components/ErrorDialog.qml")
|
|
var popup = comp.createObject(app, props)
|
|
popup.open();
|
|
}
|
|
}
|
|
}
|
|
|
|
ThingsProxy {
|
|
id: nodeThings
|
|
engine: _engine
|
|
paramsFilter: {"ieeeAddress": root.node.ieeeAddress}
|
|
}
|
|
|
|
property int signalStrength: node ? Math.round(node.lqi * 100.0 / 255.0) : 0
|
|
|
|
NymeaItemDelegate {
|
|
Layout.fillWidth: true
|
|
text: root.node.model
|
|
subText: qsTr("Model")
|
|
prominentSubText: false
|
|
progressive: false
|
|
}
|
|
NymeaItemDelegate {
|
|
prominentSubText: false
|
|
progressive: false
|
|
Layout.fillWidth: true
|
|
text: root.node.manufacturer
|
|
subText: qsTr("Manufacturer")
|
|
}
|
|
|
|
NymeaItemDelegate {
|
|
prominentSubText: false
|
|
progressive: false
|
|
Layout.fillWidth: true
|
|
text: root.node.ieeeAddress
|
|
subText: qsTr("IEEE address")
|
|
font: Style.smallFont
|
|
}
|
|
NymeaItemDelegate {
|
|
prominentSubText: false
|
|
progressive: false
|
|
Layout.fillWidth: true
|
|
text: "0x" + root.node.networkAddress.toString(16)
|
|
subText: qsTr("Network address")
|
|
}
|
|
NymeaItemDelegate {
|
|
prominentSubText: false
|
|
progressive: false
|
|
Layout.fillWidth: true
|
|
text: (root.node.lqi * 100 / 255).toFixed(0) + " %"
|
|
subText: qsTr("Signal strength")
|
|
}
|
|
NymeaItemDelegate {
|
|
prominentSubText: false
|
|
progressive: false
|
|
Layout.fillWidth: true
|
|
text: root.node.version.length > 0 ? root.node.version : qsTr("Unknown")
|
|
subText: qsTr("Version")
|
|
}
|
|
|
|
NymeaItemDelegate {
|
|
Layout.fillWidth: true
|
|
text: qsTr("Device endpoints")
|
|
subText: qsTr("Show detailed information about the node")
|
|
onClicked: pageStack.push(endpointsPageComponent)
|
|
}
|
|
|
|
SettingsPageSectionHeader {
|
|
text: qsTr("Associated things")
|
|
}
|
|
|
|
Repeater {
|
|
model: nodeThings
|
|
delegate: NymeaItemDelegate {
|
|
Layout.fillWidth: true
|
|
property Thing thing: nodeThings.get(index)
|
|
iconName: app.interfacesToIcon(thing.thingClass.interfaces)
|
|
text: thing.name
|
|
onClicked: pageStack.push("/ui/thingconfiguration/ConfigureThingPage.qml", {thing: thing})
|
|
}
|
|
|
|
// delegate: RowLayout {
|
|
// id: thingDelegate
|
|
// Layout.leftMargin: Style.margins
|
|
// Layout.rightMargin: Style.margins
|
|
// property Thing thing: nodeThings.get(index)
|
|
// Layout.fillWidth: true
|
|
// ColorIcon {
|
|
// size: Style.iconSize
|
|
// source: app.interfacesToIcon(thing.thingClass.interfaces)
|
|
// color: Style.accentColor
|
|
// }
|
|
// TextField {
|
|
// text: thingDelegate.thing.name
|
|
// Layout.fillWidth: true
|
|
// onEditingFinished: engine.thingManager.editThing(thingDelegate.thing.id, text)
|
|
// }
|
|
// }
|
|
}
|
|
|
|
|
|
ColumnLayout {
|
|
visible: engine.jsonRpcClient.ensureServerVersion("6.2")
|
|
|
|
SettingsPageSectionHeader {
|
|
text: qsTr("Bindings")
|
|
}
|
|
|
|
Repeater {
|
|
model: root.node.bindings
|
|
delegate: NymeaSwipeDelegate {
|
|
id: bindingDelegate
|
|
Layout.fillWidth: true
|
|
property ZigbeeNodeBinding binding: root.node.bindings[index]
|
|
property ZigbeeNode destinationNode: root.network.nodes.getNode(binding.destinationAddress)
|
|
property ZigbeeNodeEndpoint endpoint: root.node.getEndpoint(binding.sourceEndpointId);
|
|
property ZigbeeCluster inputCluster: endpoint ? endpoint.getInputCluster(binding.clusterId) : null
|
|
property ZigbeeCluster outputCluster: endpoint ? endpoint.getOutputCluster(binding.clusterId) : null
|
|
property ZigbeeCluster usedCluster: inputCluster ? inputCluster : outputCluster
|
|
property Thing destinationThing: destinationThings.count > 0 ? destinationThings.get(0) : null
|
|
ThingsProxy {
|
|
id: destinationThings
|
|
engine: _engine
|
|
paramsFilter: {"ieeeAddress": bindingDelegate.binding.destinationAddress}
|
|
}
|
|
|
|
iconName: destinationNode && destinationNode == root.coordinatorNode
|
|
? "qrc:/styles/%1/logo.svg".arg(styleController.currentStyle)
|
|
: destinationThing
|
|
? app.interfacesToIcon(destinationThing.thingClass.interfaces)
|
|
: "/ui/images/zigbee.svg"
|
|
canDelete: true
|
|
progressive: false
|
|
text: {
|
|
if (binding.destinationAddress == "") {
|
|
return qsTr("Group: 0x%1").arg(NymeaUtils.pad(binding.groupAddress.toString(16), 4))
|
|
}
|
|
var ret = ""
|
|
if (destinationNode) {
|
|
if (destinationNode == root.coordinatorNode) {
|
|
ret += Configuration.systemName
|
|
} else {
|
|
ret += destinationNode.model
|
|
}
|
|
} else {
|
|
ret += binding.destinationAddress
|
|
}
|
|
|
|
if (destinationThings.count == 1) {
|
|
ret += " (" + destinationThings.get(0).name + ")"
|
|
} else if (destinationThings.count > 1) {
|
|
ret += " (" + destinationThings.count + " things)"
|
|
}
|
|
|
|
return ret
|
|
}
|
|
subText: {
|
|
var ret = usedCluster.clusterName();
|
|
if (binding.destinationAddress != "") {
|
|
ret += " (" + binding.sourceEndpointId + " -> " + binding.destinationEndpointId + ")"
|
|
}
|
|
return ret;
|
|
}
|
|
onDeleteClicked: {
|
|
if (!node.rxOnWhenIdle) {
|
|
d.wakeupDialog = wakeupDialogComponent.createObject(root)
|
|
d.wakeupDialog.open()
|
|
}
|
|
d.pendingCommandId = zigbeeManager.removeBinding(network.networkUuid, binding)
|
|
}
|
|
}
|
|
}
|
|
|
|
Button {
|
|
Layout.fillWidth: true
|
|
Layout.leftMargin: Style.margins
|
|
Layout.rightMargin: Style.margins
|
|
text: qsTr("Add binding")
|
|
onClicked: {
|
|
var dialog = addBindingComponent.createObject(root)
|
|
dialog.open()
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Component {
|
|
id: removeZigbeeNodeDialogComponent
|
|
|
|
MeaDialog {
|
|
id: removeZigbeeNodeDialog
|
|
|
|
property ZigbeeNode zigbeeNode
|
|
|
|
headerIcon: "/ui/images/zigbee.svg"
|
|
title: qsTr("Remove ZigBee node") + " " + (zigbeeNode ? zigbeeNode.model : "")
|
|
text: qsTr("Are you sure you want to remove this node from the network?")
|
|
standardButtons: Dialog.Ok | Dialog.Cancel
|
|
|
|
Label {
|
|
text: qsTr("Please note that if this node has been assigned to a thing, it will also be removed from the system.")
|
|
Layout.fillWidth: true
|
|
wrapMode: Text.WordWrap
|
|
}
|
|
|
|
onAccepted: {
|
|
d.removeNode(zigbeeNode.networkUuid, zigbeeNode.ieeeAddress)
|
|
}
|
|
}
|
|
}
|
|
|
|
Component {
|
|
id: endpointsPageComponent
|
|
SettingsPageBase {
|
|
title: qsTr("Node descriptor")
|
|
|
|
header: NymeaHeader {
|
|
text: qsTr("ZigBee node descriptor")
|
|
backButtonVisible: true
|
|
onBackPressed: pageStack.pop()
|
|
|
|
HeaderButton {
|
|
imageSource: "/ui/images/edit-copy.svg"
|
|
text: qsTr("Copy")
|
|
onClicked: {
|
|
PlatformHelper.toClipBoard(descriptorText.text)
|
|
ToolTip.show(qsTr("Copied to clipboard"), 1000);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
TextArea {
|
|
id: descriptorText
|
|
readOnly: true
|
|
Layout.fillWidth: true
|
|
leftPadding: Style.margins
|
|
rightPadding: Style.margins
|
|
topPadding: Style.margins
|
|
bottomPadding: Style.margins
|
|
font.family: "UbuntuMono"
|
|
font.pixelSize: Style.smallFont.pixelSize
|
|
|
|
text: {
|
|
var ret = "Manufacturer: " + root.node.manufacturer + "\n"
|
|
ret += "Model: " + root.node.model + "\n"
|
|
ret += "RxOnWhileIdle: " + root.node.rxOnWhenIdle + "\n"
|
|
ret += "Basic cluster version: " + root.node.version + "\n"
|
|
|
|
if (root.node.endpoints.length > 0) {
|
|
ret += "Endpoints\n";
|
|
}
|
|
|
|
for (var i = 0; i < root.node.endpoints.length; i++) {
|
|
var endpoint = root.node.endpoints[i]
|
|
var isLastEp = i == root.node.endpoints.length - 1;
|
|
var hasInputClusters = endpoint.inputClusters.length > 0
|
|
var hasOutputClusters = endpoint.outputClusters.length > 0
|
|
ret += (isLastEp ? "└" : "├") + (hasInputClusters || hasOutputClusters ? "┬" : "─") + " " + endpoint.endpointId + "\n"
|
|
ret += (isLastEp ? " " : "│") + (hasOutputClusters ? "├" : "└") + (hasInputClusters ? "┬" : "─") + " Input clusters\n"
|
|
for (var j = 0; j < endpoint.inputClusters.length; j++) {
|
|
var cluster = endpoint.inputClusters[j]
|
|
var isLast = j == endpoint.inputClusters.length - 1
|
|
ret += (isLastEp ? " " : "│") + (hasOutputClusters ? "│" : " ") + (isLast ? "└" : "├") + "─ 0x" + NymeaUtils.pad(cluster.clusterId, 4, 16) + " " + cluster.clusterName() + " (" + (cluster.direction == ZigbeeCluster.ZigbeeClusterDirectionClient ? qsTr("Client") : qsTr("Server")) + ")\n"
|
|
}
|
|
if (hasOutputClusters) {
|
|
ret += (isLastEp ? " " : "│") + "└" + (hasOutputClusters ? "┬" : "─") +" Output clusters\n"
|
|
for (var j = 0; j < endpoint.outputClusters.length; j++) {
|
|
var cluster = endpoint.outputClusters[j]
|
|
var isLast = j == endpoint.outputClusters.length - 1
|
|
ret += (isLastEp ? " " : "│") + " " + (isLast ? "└" : "├") + "─ 0x" + NymeaUtils.pad(cluster.clusterId, 4, 16) + " " + cluster.clusterName() + " (" + (cluster.direction == ZigbeeCluster.ZigbeeClusterDirectionClient ? qsTr("Client") : qsTr("Server")) + ")\n"
|
|
}
|
|
}
|
|
|
|
}
|
|
return ret;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
Component {
|
|
id: addBindingComponent
|
|
MeaDialog {
|
|
title: qsTr("Add binding")
|
|
|
|
Label {
|
|
text: qsTr("Source endpoint")
|
|
Layout.fillWidth: true
|
|
}
|
|
ComboBox {
|
|
Layout.fillWidth: true
|
|
id: sourceEndpointComboBox
|
|
model: root.node.endpoints
|
|
textRole: "endpointId"
|
|
displayText: currentEndpoint.endpointId
|
|
property ZigbeeNodeEndpoint currentEndpoint: root.node.endpoints[currentIndex]
|
|
onCurrentEndpointChanged: print("source endpoint changed", currentEndpoint.endpointId)
|
|
}
|
|
Label {
|
|
text: qsTr("Target")
|
|
Layout.fillWidth: true
|
|
}
|
|
|
|
RowLayout {
|
|
// Groups not properly implemented yet. hiding it for now
|
|
visible: false
|
|
RadioButton {
|
|
id: nodeRadioButton
|
|
text: qsTr("Node")
|
|
checked: true
|
|
Layout.fillWidth: true
|
|
}
|
|
RadioButton {
|
|
id: groupRadioButton
|
|
text: qsTr("Group")
|
|
Layout.fillWidth: true
|
|
}
|
|
}
|
|
|
|
ComboBox {
|
|
id: destinationNodeComboBox
|
|
Layout.fillWidth: true
|
|
Layout.preferredHeight: Style.delegateHeight
|
|
model: network.nodes
|
|
visible: nodeRadioButton.checked
|
|
property ZigbeeNode currentNode: network.nodes.get(currentIndex)
|
|
property Thing currentNodeThing: currentNode && currentDestinationNodeThings.count > 0 ? currentDestinationNodeThings.get(0) : null
|
|
ThingsProxy {
|
|
id: currentDestinationNodeThings
|
|
engine: _engine
|
|
paramsFilter: destinationNodeComboBox.currentNode ? {"ieeeAddress": destinationNodeComboBox.currentNode.ieeeAddress} : {}
|
|
}
|
|
|
|
contentItem: RowLayout {
|
|
id: destinationNodeContentItem
|
|
width: parent.width - destinationNodeComboBox.indicator.width - Style.smallMargins
|
|
height: Style.delegateHeight
|
|
spacing: Style.smallMargins
|
|
|
|
ColorIcon {
|
|
Layout.leftMargin: Style.smallMargins
|
|
size: Style.iconSize
|
|
name: destinationNodeComboBox.currentNode == root.coordinatorNode
|
|
? "qrc:/styles/%1/logo.svg".arg(styleController.currentStyle)
|
|
: destinationNodeComboBox.currentNodeThing
|
|
? app.interfacesToIcon(destinationNodeComboBox.currentNodeThing.thingClass.interfaces)
|
|
: "/ui/images/zigbee.svg"
|
|
color: Style.accentColor
|
|
}
|
|
|
|
ColumnLayout {
|
|
Label {
|
|
Layout.fillWidth: true
|
|
text: destinationNodeComboBox.currentNode == root.coordinatorNode
|
|
? Configuration.systemName
|
|
: destinationNodeComboBox.currentNode.model + " - " + destinationNodeComboBox.currentNode.manufacturer
|
|
elide: Text.ElideRight
|
|
}
|
|
Label {
|
|
Layout.fillWidth: true
|
|
text: destinationNodeComboBox.currentNode == root.coordinatorNode
|
|
? qsTr("Coordinator")
|
|
: currentDestinationNodeThings.count == 1
|
|
? destinationNodeComboBox.currentNodeThing.name
|
|
: currentDestinationNodeThings.count > 1
|
|
? qsTr("%1 things").arg(currentDestinationNodeThings.count)
|
|
: qsTr("Unrecognized device")
|
|
font: Style.smallFont
|
|
elide: Text.ElideRight
|
|
}
|
|
}
|
|
}
|
|
delegate: NymeaItemDelegate {
|
|
id: destinationNodeDelegate
|
|
property ZigbeeNode node: network.nodes.get(index)
|
|
property Thing nodeThing: destinationNodeThings.count > 0 ? destinationNodeThings.get(0) : null
|
|
iconName: node == coordinatorNode
|
|
? "qrc:/styles/%1/logo.svg".arg(styleController.currentStyle)
|
|
: nodeThing ? app.interfacesToIcon(nodeThing.thingClass.interfaces) : "/ui/images/zigbee.svg"
|
|
width: parent.width
|
|
text: node == root.coordinatorNode
|
|
? Configuration.systemName
|
|
: node.model + " - " + node.manufacturer
|
|
subText: node == root.coordinatorNode
|
|
? qsTr("Coordinator")
|
|
: destinationNodeThings.count == 1
|
|
? nodeThing.name
|
|
: destinationNodeThings.count > 1
|
|
? qsTr("%1 things").arg(destinationNodeThings.count)
|
|
: qsTr("Unrecognized device")
|
|
progressive: false
|
|
|
|
ThingsProxy {
|
|
id: destinationNodeThings
|
|
engine: _engine
|
|
paramsFilter: {"ieeeAddress": destinationNodeDelegate.node.ieeeAddress}
|
|
}
|
|
}
|
|
}
|
|
Label {
|
|
visible: nodeRadioButton.checked
|
|
text: qsTr("Destination endpoint")
|
|
Layout.fillWidth: true
|
|
}
|
|
ComboBox {
|
|
id: destinationEndpointComboBox
|
|
visible: nodeRadioButton.checked
|
|
Layout.fillWidth: true
|
|
model: destinationNodeComboBox.currentNode.endpoints
|
|
textRole: "endpointId"
|
|
displayText: currentEndpoint.endpointId
|
|
property ZigbeeNodeEndpoint currentEndpoint: destinationNodeComboBox.currentNode.endpoints[currentIndex]
|
|
}
|
|
|
|
Label {
|
|
text: qsTr("Group address")
|
|
visible: groupRadioButton.checked
|
|
}
|
|
|
|
TextField {
|
|
id: groupAddressTextField
|
|
visible: groupRadioButton.checked
|
|
Layout.fillWidth: true
|
|
text: "0"
|
|
}
|
|
|
|
Label {
|
|
text: qsTr("Cluster")
|
|
Layout.fillWidth: true
|
|
}
|
|
|
|
ComboBox {
|
|
id: clusterComboBox
|
|
Layout.fillWidth: true
|
|
delegate: ItemDelegate {
|
|
width: parent.width
|
|
text: modelData.clusterName()
|
|
}
|
|
model: {
|
|
var ret = []
|
|
if (nodeRadioButton.checked) {
|
|
print("updating clusters", sourceEndpointComboBox.currentEndpoint, destinationNodeComboBox.currentNode, destinationEndpointComboBox.currentEndpoint)
|
|
if (!sourceEndpointComboBox.currentEndpoint || !destinationNodeComboBox.currentNode || !destinationEndpointComboBox.currentEndpoint) {
|
|
return ret;
|
|
}
|
|
|
|
if (destinationNodeComboBox.currentNode == root.coordinatorNode) {
|
|
for (var i = 0; i < sourceEndpointComboBox.currentEndpoint.outputClusters.length; i++) {
|
|
var outputCluster = sourceEndpointComboBox.currentEndpoint.outputClusters[i]
|
|
ret.push(outputCluster)
|
|
}
|
|
for (var i = 0; i < sourceEndpointComboBox.currentEndpoint.inputClusters.length; i++) {
|
|
var inputCluster = sourceEndpointComboBox.currentEndpoint.inputClusters[i]
|
|
ret.push(inputCluster)
|
|
}
|
|
} else {
|
|
for (var i = 0; i < sourceEndpointComboBox.currentEndpoint.outputClusters.length; i++) {
|
|
var outputCluster = sourceEndpointComboBox.currentEndpoint.outputClusters[i]
|
|
print("source has cluster", outputCluster.clusterId)
|
|
for (var j = 0; j < destinationEndpointComboBox.currentEndpoint.inputClusters.length; j++) {
|
|
var inputCluster = destinationEndpointComboBox.currentEndpoint.inputClusters[j]
|
|
print("destination has cluster", inputCluster.clusterId)
|
|
if (inputCluster.clusterId === outputCluster.clusterId && inputCluster.direction !== outputCluster.direction) {
|
|
ret.push(outputCluster);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
for (var i = 0; i < sourceEndpointComboBox.currentEndpoint.inputClusters.length; i++) {
|
|
var inputCluster = sourceEndpointComboBox.currentEndpoint.inputClusters[i]
|
|
print("source has cluster", inputCluster.clusterId)
|
|
for (var j = 0; j < destinationEndpointComboBox.currentEndpoint.outputClusters.length; j++) {
|
|
var outputCluster = destinationEndpointComboBox.currentEndpoint.outputClusters[j]
|
|
print("destination has cluster", outputCluster.clusterId)
|
|
if (inputCluster.clusterId === outputCluster.clusterId && inputCluster.direction !== outputCluster.direction) {
|
|
ret.push(inputCluster);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
for (var i = 0; i < sourceEndpointComboBox.currentEndpoint.inputClusters.length; i++) {
|
|
var inputCluster = sourceEndpointComboBox.currentEndpoint.inputClusters[i]
|
|
ret.push(inputCluster);
|
|
}
|
|
}
|
|
|
|
return ret
|
|
}
|
|
property ZigbeeCluster currentCluster: currentValue
|
|
displayText: currentValue.clusterName()
|
|
}
|
|
|
|
onAccepted: {
|
|
if (nodeRadioButton.checked) {
|
|
d.pendingCommandId = root.zigbeeManager.createBinding(
|
|
root.network.networkUuid,
|
|
root.node.ieeeAddress,
|
|
sourceEndpointComboBox.currentEndpoint.endpointId,
|
|
clusterComboBox.currentCluster.clusterId,
|
|
destinationNodeComboBox.currentNode.ieeeAddress,
|
|
destinationEndpointComboBox.currentEndpoint.endpointId)
|
|
} else {
|
|
d.pendingCommandId = root.zigbeeManager.createGroupBinding(
|
|
root.network.networkUuid,
|
|
root.node.ieeeAddress,
|
|
sourceEndpointComboBox.currentEndpoint.endpointId,
|
|
clusterComboBox.currentCluster.clusterId,
|
|
groupAddressTextField.text)
|
|
}
|
|
|
|
if (!root.node.rxOnWhenIdle) {
|
|
d.wakeupDialog = wakeupDialogComponent.createObject(root)
|
|
d.wakeupDialog.open()
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
Component {
|
|
id: wakeupDialogComponent
|
|
MeaDialog {
|
|
id: wakeupDialog
|
|
title: qsTr("Wake up %1").arg(root.node.model)
|
|
text: qsTr("The selected node is a sleepy device. Please wake up the device by pressing a button.")
|
|
}
|
|
}
|
|
}
|