mirror of
https://github.com/home-assistant/frontend.git
synced 2025-07-13 12:26:35 +00:00
[WIP] Zwave panel (#260)
* Add Node card * Add Node selection dropdown * Add refresh node service and auto visible options * Add replace node and replace failed node to node options * Add node information * Add node group configuration * Add Wakeup and fix group associations * Make Node info expandable * Add refresh entity * Cleanup * Add set_config and print_config parameter * styling * indention * lint error * thank you @adgelbfish * Hide correctly * Add Entity info * Indents * Add Group fetched from API * Add API to get config options * Initialize empty array * Add config handling * add OZW log * missing style * Bug in other groupmembers * Fix set-configparameter * Fix set-association * Tweaks to associations * Add usercodes * Tweaks * Tweaks * Target node text * Move computed servicedata to property * Start splitting * Split part 2, network * Splitting 3 * cleanup * refresh on setting with delay * fix servicedata * Splitting 4 groups * Splitting 5 config and wakeup * Splitting done. * Final tweaks, lint and removal of logging
This commit is contained in:
parent
ffe0b22d77
commit
ad3b3ce3dc
@ -4,9 +4,19 @@
|
|||||||
<link rel="import" href="../../bower_components/app-layout/app-header-layout/app-header-layout.html">
|
<link rel="import" href="../../bower_components/app-layout/app-header-layout/app-header-layout.html">
|
||||||
<link rel="import" href="../../bower_components/app-layout/app-header/app-header.html">
|
<link rel="import" href="../../bower_components/app-layout/app-header/app-header.html">
|
||||||
<link rel="import" href="../../bower_components/app-layout/app-toolbar/app-toolbar.html">
|
<link rel="import" href="../../bower_components/app-layout/app-toolbar/app-toolbar.html">
|
||||||
|
<link rel="import" href="../../bower_components/paper-dropdown-menu/paper-dropdown-menu.html">
|
||||||
|
<link rel='import' href='../../bower_components/paper-item/paper-item.html'>
|
||||||
|
<link rel='import' href="../../bower_components/paper-listbox/paper-listbox.html">
|
||||||
|
<link rel='import' href="../../bower_components/paper-input/paper-input.html">
|
||||||
|
|
||||||
<link rel="import" href="../../src/components/buttons/ha-call-service-button.html">
|
<link rel="import" href="../../src/components/buttons/ha-call-service-button.html">
|
||||||
<link rel="import" href="../../src/resources/ha-style.html">
|
<link rel="import" href="../../src/resources/ha-style.html">
|
||||||
|
<link rel="import" href="./zwave-log.html">
|
||||||
|
<link rel="import" href="./zwave-network.html">
|
||||||
|
<link rel="import" href="./zwave-node-information.html">
|
||||||
|
<link rel="import" href="./zwave-node-config.html">
|
||||||
|
<link rel="import" href="./zwave-usercodes.html">
|
||||||
|
<link rel="import" href="./zwave-groups.html">
|
||||||
|
|
||||||
<dom-module id="ha-panel-zwave">
|
<dom-module id="ha-panel-zwave">
|
||||||
<template>
|
<template>
|
||||||
@ -15,14 +25,28 @@
|
|||||||
margin-top: 24px;
|
margin-top: 24px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.node-info {
|
||||||
|
margin-left: 16px;
|
||||||
|
text-transform: capitalize;
|
||||||
|
}
|
||||||
|
|
||||||
|
.help-text {
|
||||||
|
padding-left: 24px;
|
||||||
|
padding-right: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
paper-card {
|
paper-card {
|
||||||
display: block;
|
display: block;
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
max-width: 600px;
|
max-width: 600px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.card-actions.warning ha-call-service-button {
|
.device-picker {
|
||||||
color: var(--google-red-500);
|
@apply(--layout-horizontal);
|
||||||
|
@apply(--layout-center-center);
|
||||||
|
padding-left: 24px;
|
||||||
|
padding-right: 24px;
|
||||||
|
padding-bottom: 24px;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
<app-header-layout has-scrolling-region>
|
<app-header-layout has-scrolling-region>
|
||||||
@ -34,63 +58,152 @@
|
|||||||
</app-header>
|
</app-header>
|
||||||
|
|
||||||
<div class='content'>
|
<div class='content'>
|
||||||
<paper-card heading='Z-Wave Network Management'>
|
<zwave-network
|
||||||
<div class='card-content'>
|
id='zwave-network'
|
||||||
Z-Wave Network controls.
|
hass='[[hass]]'
|
||||||
|
></zwave-network>
|
||||||
</div>
|
</div>
|
||||||
|
<!--Node card-->
|
||||||
|
<div class='content'>
|
||||||
|
<paper-card heading='Z-Wave Node Management'>
|
||||||
|
<div class='card-content'>
|
||||||
|
Z-Wave Node controls.
|
||||||
|
</div>
|
||||||
|
<div class='device-picker'>
|
||||||
|
<paper-dropdown-menu label="Nodes" class="flex">
|
||||||
|
<paper-listbox
|
||||||
|
class="dropdown-content"
|
||||||
|
selected='{{selectedNode}}'>
|
||||||
|
<template is='dom-repeat' items='[[nodes]]' as='state'>
|
||||||
|
<paper-item>[[computeSelectCaption(state)]]</paper-item>
|
||||||
|
</template>
|
||||||
|
</paper-listbox>
|
||||||
|
</paper-dropdown-menu>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<template is='dom-if' if='[[!computeIsNodeSelected(selectedNode)]]'>
|
||||||
<div class='card-actions'>
|
<div class='card-actions'>
|
||||||
<ha-call-service-button
|
<ha-call-service-button
|
||||||
hass='[[hass]]'
|
hass='[[hass]]'
|
||||||
domain='zwave'
|
domain='zwave'
|
||||||
service='add_node_secure'
|
service='refresh_node'
|
||||||
>Add Node</ha-call-service-button>
|
service-data=[[computeNodeServiceData(selectedNode)]]
|
||||||
|
>Refresh Node</ha-call-service-button>
|
||||||
<ha-call-service-button
|
<ha-call-service-button
|
||||||
hass='[[hass]]'
|
hass='[[hass]]'
|
||||||
domain='zwave'
|
domain='zwave'
|
||||||
service='remove_failed_node'
|
service='remove_failed_node'
|
||||||
|
service-data=[[computeNodeServiceData(selectedNode)]]
|
||||||
>Remove Failed Node</ha-call-service-button>
|
>Remove Failed Node</ha-call-service-button>
|
||||||
<ha-call-service-button
|
<ha-call-service-button
|
||||||
hass='[[hass]]'
|
hass='[[hass]]'
|
||||||
domain='zwave'
|
domain='zwave'
|
||||||
service='remove_node'
|
service='replace_failed_node'
|
||||||
>Remove Node</ha-call-service-button>
|
service-data=[[computeNodeServiceData(selectedNode)]]
|
||||||
</div>
|
>Replace Failed Node</ha-call-service-button>
|
||||||
<div class='card-actions warning'>
|
|
||||||
<ha-call-service-button
|
<ha-call-service-button
|
||||||
hass='[[hass]]'
|
hass='[[hass]]'
|
||||||
domain='zwave'
|
domain='zwave'
|
||||||
service='cancel_command'
|
service='print_node'
|
||||||
>Cancel Command</ha-call-service-button>
|
service-data=[[computeNodeServiceData(selectedNode)]]
|
||||||
|
>Print Node</ha-call-service-button>
|
||||||
</div>
|
</div>
|
||||||
|
<div class='card-actions'>
|
||||||
|
<paper-input
|
||||||
|
float-label="New node name"
|
||||||
|
type=text
|
||||||
|
value={{newNodeNameInput}}
|
||||||
|
placeholder=[[computeGetNodeName(selectedNode)]]>
|
||||||
|
</paper-input>
|
||||||
|
<ha-call-service-button
|
||||||
|
hass='[[hass]]'
|
||||||
|
domain='zwave'
|
||||||
|
service='rename_node'
|
||||||
|
service-data=[[computeNodeNameServiceData(newNodeNameInput)]]
|
||||||
|
>Rename Node</ha-call-service-button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class='device-picker'>
|
||||||
|
<paper-dropdown-menu label="Entities of this node" class="flex">
|
||||||
|
<paper-listbox
|
||||||
|
class="dropdown-content"
|
||||||
|
selected='{{selectedEntity}}'>
|
||||||
|
<template is='dom-repeat' items='[[entities]]' as='state'>
|
||||||
|
<paper-item>[[computeSelectCaptionEnt(state)]]</paper-item>
|
||||||
|
</template>
|
||||||
|
</paper-listbox>
|
||||||
|
</paper-dropdown-menu>
|
||||||
|
</div>
|
||||||
|
<template is='dom-if' if='[[!computeIsEntitySelected(selectedEntity)]]'>
|
||||||
<div class='card-actions'>
|
<div class='card-actions'>
|
||||||
<ha-call-service-button
|
<ha-call-service-button
|
||||||
hass='[[hass]]'
|
hass='[[hass]]'
|
||||||
domain='zwave'
|
domain='zwave'
|
||||||
service='heal_network'
|
service='refresh_entity'
|
||||||
>Heal Network</ha-call-service-button>
|
service-data=[[computeRefreshEntityServiceData(selectedEntity)]]
|
||||||
<ha-call-service-button
|
>Refresh Entity</ha-call-service-button>
|
||||||
hass='[[hass]]'
|
|
||||||
domain='zwave'
|
|
||||||
service='start_network'
|
|
||||||
>Start Network</ha-call-service-button>
|
|
||||||
<ha-call-service-button
|
|
||||||
hass='[[hass]]'
|
|
||||||
domain='zwave'
|
|
||||||
service='stop_network'
|
|
||||||
>Stop Network</ha-call-service-button>
|
|
||||||
<ha-call-service-button
|
|
||||||
hass='[[hass]]'
|
|
||||||
domain='zwave'
|
|
||||||
service='soft_reset'
|
|
||||||
>Soft Reset</ha-call-service-button>
|
|
||||||
<ha-call-service-button
|
|
||||||
hass='[[hass]]'
|
|
||||||
domain='zwave'
|
|
||||||
service='test_network'
|
|
||||||
>Test Network</ha-call-service-button>
|
|
||||||
</div>
|
</div>
|
||||||
|
<div class='content'>
|
||||||
|
<div class='card-actions'>
|
||||||
|
<paper-button toggles raised noink active={{entityInfoActive}}>Entity Attributes</paper-button>
|
||||||
|
</div>
|
||||||
|
<template is='dom-if' if={{entityInfoActive}}>
|
||||||
|
<template is='dom-repeat' items='[[selectedEntityAttrs]]' as='state'>
|
||||||
|
<div class='node-info'>
|
||||||
|
<span>[[state]]</span>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</template>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</template>
|
||||||
|
</template>
|
||||||
</paper-card>
|
</paper-card>
|
||||||
</div>
|
</div>
|
||||||
|
<!--Node info card-->
|
||||||
|
<template is='dom-if' if='[[!computeIsNodeSelected(selectedNode)]]'>
|
||||||
|
<zwave-node-information
|
||||||
|
id='zwave-node-information'
|
||||||
|
nodes='[[nodes]]'
|
||||||
|
selected-node='[[selectedNode]]'
|
||||||
|
></zwave-node-information>
|
||||||
|
</template>
|
||||||
|
<!--Group card-->
|
||||||
|
<template is='dom-if' if='[[!computeIsNodeSelected(selectedNode)]]'>
|
||||||
|
<zwave-groups
|
||||||
|
hass='[[hass]]'
|
||||||
|
nodes='[[nodes]]'
|
||||||
|
selected-node='[[selectedNode]]'
|
||||||
|
groups='[[groups]]'
|
||||||
|
></zwave-groups>
|
||||||
|
</template>
|
||||||
|
<!--Config card-->
|
||||||
|
<template is='dom-if' if='[[!computeIsNodeSelected(selectedNode)]]'>
|
||||||
|
<zwave-node-config
|
||||||
|
hass='[[hass]]'
|
||||||
|
nodes='[[nodes]]'
|
||||||
|
selected-node='[[selectedNode]]'
|
||||||
|
config='[[config]]'
|
||||||
|
></zwave-node-config>
|
||||||
|
</template>
|
||||||
|
<!--User Codes-->
|
||||||
|
<template is='dom-if' if='{{hasNodeUserCodes}}'>
|
||||||
|
<zwave-usercodes
|
||||||
|
id='zwave-usercodes'
|
||||||
|
hass='[[hass]]'
|
||||||
|
nodes='[[nodes]]'
|
||||||
|
user-codes='[[userCodes]]'
|
||||||
|
selected-node='[[selectedNode]]'
|
||||||
|
></zwave-usercodes>
|
||||||
|
</template>
|
||||||
|
<!--Ozw log-->
|
||||||
|
<div class='content'>
|
||||||
|
<ozw-log
|
||||||
|
id='ozw-log'
|
||||||
|
hass='[[hass]]'
|
||||||
|
></ozw-log>
|
||||||
|
</div>
|
||||||
|
|
||||||
</app-header-layout>
|
</app-header-layout>
|
||||||
</template>
|
</template>
|
||||||
</dom-module>
|
</dom-module>
|
||||||
@ -112,6 +225,196 @@ Polymer({
|
|||||||
type: Boolean,
|
type: Boolean,
|
||||||
value: false,
|
value: false,
|
||||||
},
|
},
|
||||||
|
|
||||||
|
nodes: {
|
||||||
|
type: Array,
|
||||||
|
computed: 'computeNodes(hass)'
|
||||||
|
},
|
||||||
|
|
||||||
|
selectedNode: {
|
||||||
|
type: Number,
|
||||||
|
value: -1,
|
||||||
|
observer: 'selectedNodeChanged'
|
||||||
|
},
|
||||||
|
|
||||||
|
config: {
|
||||||
|
type: Array,
|
||||||
|
value: function () {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
entities: {
|
||||||
|
type: Array,
|
||||||
|
computed: 'computeEntities(selectedNode)',
|
||||||
|
},
|
||||||
|
|
||||||
|
entityInfoActive: {
|
||||||
|
type: Boolean,
|
||||||
|
},
|
||||||
|
|
||||||
|
selectedEntity: {
|
||||||
|
type: Number,
|
||||||
|
value: -1,
|
||||||
|
observers: ['computeIsEntitySelected',
|
||||||
|
'computeRefreshEntityServiceData']
|
||||||
|
},
|
||||||
|
|
||||||
|
selectedEntityAttrs: {
|
||||||
|
type: Array,
|
||||||
|
computed: 'computeSelectedEntityAttrs(selectedEntity)'
|
||||||
|
},
|
||||||
|
|
||||||
|
groups: {
|
||||||
|
type: Array,
|
||||||
|
},
|
||||||
|
|
||||||
|
newNodeNameInput: {
|
||||||
|
type: String,
|
||||||
|
},
|
||||||
|
|
||||||
|
userCodes: {
|
||||||
|
type: Array,
|
||||||
|
value: function () {
|
||||||
|
return [];
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
hasNodeUserCodes: {
|
||||||
|
type: Boolean,
|
||||||
|
value: false
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
computeNodes: function (hass) {
|
||||||
|
return Object.keys(hass.states)
|
||||||
|
.map(function (key) { return hass.states[key]; })
|
||||||
|
.filter(function (ent) {
|
||||||
|
return (!ent.attributes.hidden &&
|
||||||
|
(ent.entity_id).match('zwave[.]'));
|
||||||
|
})
|
||||||
|
.sort(function (entityA, entityB) {
|
||||||
|
if (entityA.entity_id < entityB.entity_id) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (entityA.entity_id > entityB.entity_id) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
computeEntities: function (selectedNode) {
|
||||||
|
if (!this.nodes || selectedNode === -1) return -1;
|
||||||
|
var hass = this.hass;
|
||||||
|
var nodeid = this.nodes[this.selectedNode].attributes.node_id;
|
||||||
|
return Object.keys(hass.states)
|
||||||
|
.map(function (key) { return hass.states[key]; })
|
||||||
|
.filter(function (ent) {
|
||||||
|
if (ent.attributes.node_id === undefined) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return (!ent.attributes.hidden &&
|
||||||
|
'node_id' in ent.attributes &&
|
||||||
|
ent.attributes.node_id === nodeid &&
|
||||||
|
(!(ent.entity_id).match('zwave[.]')));
|
||||||
|
})
|
||||||
|
.sort(function (entityA, entityB) {
|
||||||
|
if (entityA.entity_id < entityB.entity_id) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (entityA.entity_id > entityB.entity_id) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
selectedNodeChanged: function (selectedNode) {
|
||||||
|
if (selectedNode === -1) return;
|
||||||
|
this.selectedConfigParameter = -1;
|
||||||
|
this.selectedConfigParameterValue = -1;
|
||||||
|
this.selectedGroup = -1;
|
||||||
|
var configData = [];
|
||||||
|
this.hass.callApi('GET', 'zwave/config/' + this.nodes[selectedNode].attributes.node_id).then(function (configs) {
|
||||||
|
Object.entries(configs).forEach(([key, value]) => {
|
||||||
|
configData.push({ key, value });
|
||||||
|
});
|
||||||
|
this.config = configData;
|
||||||
|
}.bind(this));
|
||||||
|
var groupData = [];
|
||||||
|
this.hass.callApi('GET', 'zwave/groups/' + this.nodes[selectedNode].attributes.node_id).then(function (groups) {
|
||||||
|
Object.entries(groups).forEach(([key, value]) => {
|
||||||
|
groupData.push({ key, value });
|
||||||
|
});
|
||||||
|
this.groups = groupData;
|
||||||
|
}.bind(this));
|
||||||
|
var userCodes = [];
|
||||||
|
this.hasNodeUserCodes = false;
|
||||||
|
this.notifyPath('hasNodeUserCodes');
|
||||||
|
this.hass.callApi('GET', 'zwave/usercodes/' + this.nodes[selectedNode].attributes.node_id).then(function (usercodes) {
|
||||||
|
Object.entries(usercodes).forEach(([key, value]) => {
|
||||||
|
userCodes.push({ key, value });
|
||||||
|
});
|
||||||
|
this.userCodes = userCodes;
|
||||||
|
if (Object.keys(userCodes).length === 0) {
|
||||||
|
this.hasNodeUserCodes = false;
|
||||||
|
} else {
|
||||||
|
this.hasNodeUserCodes = true;
|
||||||
|
}
|
||||||
|
this.notifyPath('hasNodeUserCodes');
|
||||||
|
}.bind(this));
|
||||||
|
},
|
||||||
|
|
||||||
|
computeSelectedEntityAttrs: function (selectedEntity) {
|
||||||
|
if (selectedEntity === -1) return 'No entity selected';
|
||||||
|
var entityAttrs = this.entities[selectedEntity].attributes;
|
||||||
|
var att = [];
|
||||||
|
Object.entries(entityAttrs).forEach(([key, value]) => {
|
||||||
|
att.push(key + ': ' + value);
|
||||||
|
});
|
||||||
|
return att.sort();
|
||||||
|
},
|
||||||
|
|
||||||
|
computeSelectCaption: function (stateObj) {
|
||||||
|
return window.hassUtil.computeStateName(stateObj) + ' (Node:' +
|
||||||
|
stateObj.attributes.node_id + ' ' +
|
||||||
|
stateObj.attributes.query_stage + ')';
|
||||||
|
},
|
||||||
|
|
||||||
|
computeSelectCaptionEnt: function (stateObj) {
|
||||||
|
return (window.hassUtil.computeDomain(stateObj) + '.'
|
||||||
|
+ window.hassUtil.computeStateName(stateObj));
|
||||||
|
},
|
||||||
|
|
||||||
|
computeIsNodeSelected: function () {
|
||||||
|
return (!this.nodes || this.selectedNode === -1);
|
||||||
|
},
|
||||||
|
|
||||||
|
computeIsEntitySelected: function (selectedEntity) {
|
||||||
|
return (selectedEntity === -1);
|
||||||
|
},
|
||||||
|
|
||||||
|
computeNodeServiceData: function (selectedNode) {
|
||||||
|
return { node_id: this.nodes[selectedNode].attributes.node_id };
|
||||||
|
},
|
||||||
|
|
||||||
|
computeGetNodeName: function (selectedNode) {
|
||||||
|
if (this.selectedNode === -1 ||
|
||||||
|
!this.nodes[selectedNode].entity_id) return -1;
|
||||||
|
var str = (this.nodes[selectedNode].entity_id);
|
||||||
|
var name = str.replace('zwave.', '');
|
||||||
|
return name;
|
||||||
|
},
|
||||||
|
|
||||||
|
computeNodeNameServiceData: function (newNodeNameInput) {
|
||||||
|
return { node_id: this.nodes[this.selectedNode].attributes.node_id,
|
||||||
|
name: newNodeNameInput };
|
||||||
|
},
|
||||||
|
|
||||||
|
computeRefreshEntityServiceData: function (selectedEntity) {
|
||||||
|
if (selectedEntity === -1) return -1;
|
||||||
|
return { entity_id: this.entities[selectedEntity].entity_id };
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
222
panels/zwave/zwave-groups.html
Normal file
222
panels/zwave/zwave-groups.html
Normal file
@ -0,0 +1,222 @@
|
|||||||
|
<link rel="import" href="../../bower_components/polymer/polymer.html">
|
||||||
|
<link rel="import" href="../../bower_components/paper-card/paper-card.html">
|
||||||
|
<link rel="import" href="../../bower_components/paper-dropdown-menu/paper-dropdown-menu.html">
|
||||||
|
<link rel='import' href='../../bower_components/paper-item/paper-item.html'>
|
||||||
|
<link rel='import' href="../../bower_components/paper-listbox/paper-listbox.html">
|
||||||
|
|
||||||
|
<link rel="import" href="../../src/components/buttons/ha-call-service-button.html">
|
||||||
|
|
||||||
|
<dom-module id='zwave-groups'>
|
||||||
|
<template>
|
||||||
|
<style include="iron-flex ha-style">
|
||||||
|
.content {
|
||||||
|
margin-top: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
paper-card {
|
||||||
|
display: block;
|
||||||
|
margin: 0 auto;
|
||||||
|
max-width: 600px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.device-picker {
|
||||||
|
@apply(--layout-horizontal);
|
||||||
|
@apply(--layout-center-center);
|
||||||
|
padding-left: 24px;
|
||||||
|
padding-right: 24px;
|
||||||
|
padding-bottom: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.help-text {
|
||||||
|
padding-left: 24px;
|
||||||
|
padding-right: 24px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<div class='content'>
|
||||||
|
<paper-card heading='Node group associations'>
|
||||||
|
<div class='device-picker'>
|
||||||
|
<paper-dropdown-menu label="Node to control" class='flex'>
|
||||||
|
<paper-listbox
|
||||||
|
class="dropdown-content"
|
||||||
|
selected='{{selectedTargetNode}}'>
|
||||||
|
<template is='dom-repeat' items='[[nodes]]' as='state'>
|
||||||
|
<paper-item>[[computeSelectCaption(state)]]</paper-item>
|
||||||
|
</template>
|
||||||
|
</paper-listbox>
|
||||||
|
</paper-dropdown-menu>
|
||||||
|
</div>
|
||||||
|
<template is='dom-if' if='[[!computeIsTargetNodeSelected(selectedTargetNode)]]'>
|
||||||
|
<!--TODO make api for getting groups and members-->
|
||||||
|
<div class='device-picker'>
|
||||||
|
<paper-dropdown-menu label="Group" class='flex'>
|
||||||
|
<paper-listbox
|
||||||
|
class="dropdown-content"
|
||||||
|
selected='{{selectedGroup}}'>
|
||||||
|
<template is='dom-repeat' items='[[groups]]' as='state'>
|
||||||
|
<paper-item>[[computeSelectCaptionGroup(state)]]</paper-item>
|
||||||
|
</template>
|
||||||
|
</paper-listbox>
|
||||||
|
</paper-dropdown-menu>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<template is='dom-if' if='[[!computeIsGroupSelected(selectedGroup)]]'>
|
||||||
|
<div class='help-text'>
|
||||||
|
<span>Other Nodes in this group:</span>
|
||||||
|
<template is='dom-repeat' items='[[otherGroupNodes]]' as='state'>
|
||||||
|
<span>[[state]]</span>
|
||||||
|
</template>
|
||||||
|
</div>
|
||||||
|
<div class='help-text'>
|
||||||
|
<span>Max Associations:</span>
|
||||||
|
<span>[[maxAssociations]]</span>
|
||||||
|
</div>
|
||||||
|
<div class='card-actions'>
|
||||||
|
<template is='dom-if' if='[[!noAssociationsLeft]]'>
|
||||||
|
<ha-call-service-button
|
||||||
|
hass='[[hass]]'
|
||||||
|
domain='zwave'
|
||||||
|
service='change_association'
|
||||||
|
service-data='[[computeAssocServiceData(selectedGroup, "add")]]'
|
||||||
|
>Add To Group</ha-call-service-button>
|
||||||
|
</template>
|
||||||
|
<ha-call-service-button
|
||||||
|
hass='[[hass]]'
|
||||||
|
domain='zwave'
|
||||||
|
service='change_association'
|
||||||
|
service-data='[[computeAssocServiceData(selectedGroup, "remove")]]'
|
||||||
|
>Remove From Group</ha-call-service-button>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</paper-card>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</dom-module>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
Polymer({
|
||||||
|
is: 'zwave-groups',
|
||||||
|
|
||||||
|
properties: {
|
||||||
|
hass: {
|
||||||
|
type: Object,
|
||||||
|
},
|
||||||
|
|
||||||
|
nodes: {
|
||||||
|
type: Array,
|
||||||
|
},
|
||||||
|
|
||||||
|
groups: {
|
||||||
|
type: Array,
|
||||||
|
},
|
||||||
|
|
||||||
|
selectedNode: {
|
||||||
|
type: Number,
|
||||||
|
},
|
||||||
|
|
||||||
|
selectedTargetNode: {
|
||||||
|
type: Number,
|
||||||
|
value: -1
|
||||||
|
},
|
||||||
|
|
||||||
|
selectedGroup: {
|
||||||
|
type: Number,
|
||||||
|
value: -1,
|
||||||
|
observer: 'selectedGroupChanged'
|
||||||
|
},
|
||||||
|
|
||||||
|
otherGroupNodes: {
|
||||||
|
type: Array,
|
||||||
|
value: -1,
|
||||||
|
computed: 'computeOtherGroupNodes(selectedGroup)'
|
||||||
|
},
|
||||||
|
|
||||||
|
maxAssociations: {
|
||||||
|
type: String,
|
||||||
|
value: '',
|
||||||
|
computed: 'computeMaxAssociations(selectedGroup)'
|
||||||
|
},
|
||||||
|
|
||||||
|
noAssociationsLeft: {
|
||||||
|
type: Boolean,
|
||||||
|
value: true,
|
||||||
|
computed: 'computeAssociationsLeft(selectedGroup)'
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
listeners: {
|
||||||
|
'hass-service-called': 'serviceCalled',
|
||||||
|
},
|
||||||
|
|
||||||
|
serviceCalled: function (ev) {
|
||||||
|
if (ev.detail.success) {
|
||||||
|
var foo = this;
|
||||||
|
setTimeout(function () {
|
||||||
|
foo.refreshGroups(foo.selectedNode);
|
||||||
|
}, 5000);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
computeAssociationsLeft: function (selectedGroup) {
|
||||||
|
if (selectedGroup === -1) return true;
|
||||||
|
return (this.maxAssociations === this.otherGroupNodes.length);
|
||||||
|
},
|
||||||
|
|
||||||
|
computeMaxAssociations: function (selectedGroup) {
|
||||||
|
if (selectedGroup === -1) return -1;
|
||||||
|
var maxAssociations = this.groups[selectedGroup].value.max_associations;
|
||||||
|
if (!maxAssociations) return ['None'];
|
||||||
|
return maxAssociations;
|
||||||
|
},
|
||||||
|
|
||||||
|
computeOtherGroupNodes: function (selectedGroup) {
|
||||||
|
if (selectedGroup === -1) return -1;
|
||||||
|
var associations = Object.values(this.groups[selectedGroup].value.associations);
|
||||||
|
if (!associations.length) return ['None'];
|
||||||
|
return associations;
|
||||||
|
},
|
||||||
|
|
||||||
|
computeSelectCaption: function (stateObj) {
|
||||||
|
return window.hassUtil.computeStateName(stateObj) + ' (Node:' +
|
||||||
|
stateObj.attributes.node_id + ' ' +
|
||||||
|
stateObj.attributes.query_stage + ')';
|
||||||
|
},
|
||||||
|
|
||||||
|
computeSelectCaptionGroup: function (stateObj) {
|
||||||
|
return (stateObj.key + ': ' + stateObj.value.label);
|
||||||
|
},
|
||||||
|
|
||||||
|
computeIsTargetNodeSelected: function (selectedTargetNode) {
|
||||||
|
return (!this.nodes || selectedTargetNode === -1);
|
||||||
|
},
|
||||||
|
|
||||||
|
computeIsGroupSelected: function (selectedGroup) {
|
||||||
|
return (!this.nodes || this.selectedNode === -1 || selectedGroup === -1);
|
||||||
|
},
|
||||||
|
|
||||||
|
computeAssocServiceData: function (selectedGroup, type) {
|
||||||
|
if (!this.groups === -1 || selectedGroup === -1 || this.selectedNode === -1) return -1;
|
||||||
|
return { node_id: this.nodes[this.selectedNode].attributes.node_id,
|
||||||
|
association: type,
|
||||||
|
target_node_id: this.nodes[this.selectedTargetNode].attributes.node_id,
|
||||||
|
group: this.groups[selectedGroup].key };
|
||||||
|
},
|
||||||
|
|
||||||
|
refreshGroups: function (selectedNode) {
|
||||||
|
var groupData = [];
|
||||||
|
this.hass.callApi('GET', 'zwave/groups/' + this.nodes[selectedNode].attributes.node_id).then(function (groups) {
|
||||||
|
Object.entries(groups).forEach(([key, value]) => {
|
||||||
|
groupData.push({ key, value });
|
||||||
|
});
|
||||||
|
this.groups = groupData;
|
||||||
|
this.selectedGroupChanged(this.selectedGroup);
|
||||||
|
}.bind(this));
|
||||||
|
},
|
||||||
|
|
||||||
|
selectedGroupChanged: function (selectedGroup) {
|
||||||
|
if (this.selectedGroup === -1 || selectedGroup === -1) return;
|
||||||
|
this.maxAssociations = this.groups[selectedGroup].value.max_associations;
|
||||||
|
this.otherGroupNodes = Object.values(this.groups[selectedGroup].value.associations);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
52
panels/zwave/zwave-log.html
Normal file
52
panels/zwave/zwave-log.html
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
<link rel="import" href="../../bower_components/polymer/polymer.html">
|
||||||
|
<link rel="import" href="../../bower_components/paper-card/paper-card.html">
|
||||||
|
<link rel="import" href="../../bower_components/paper-button/paper-button.html">
|
||||||
|
|
||||||
|
<dom-module id='ozw-log'>
|
||||||
|
<template>
|
||||||
|
<style include="iron-flex ha-style">
|
||||||
|
.content {
|
||||||
|
margin-top: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
paper-card {
|
||||||
|
display: block;
|
||||||
|
margin: 0 auto;
|
||||||
|
max-width: 600px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<paper-card heading='OZW Log'>
|
||||||
|
<div class='help-text'>
|
||||||
|
<pre>[[ozwLogs]]</pre>
|
||||||
|
</div>
|
||||||
|
<div class="card-actions">
|
||||||
|
<paper-button raised on-tap='refreshLog'>Refresh</paper-button>
|
||||||
|
</div>
|
||||||
|
</paper-card>
|
||||||
|
</template>
|
||||||
|
</dom-module>
|
||||||
|
<script>
|
||||||
|
|
||||||
|
Polymer({
|
||||||
|
is: 'ozw-log',
|
||||||
|
|
||||||
|
properties: {
|
||||||
|
hass: {
|
||||||
|
type: Object,
|
||||||
|
},
|
||||||
|
|
||||||
|
ozwLogs: {
|
||||||
|
type: String,
|
||||||
|
value: ''
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
refreshLog: function () {
|
||||||
|
this.ozwLogs = 'Loading ozw log...';
|
||||||
|
this.hass.callApi('GET', 'zwave/ozwlog')
|
||||||
|
.then(function (info) {
|
||||||
|
this.ozwLogs = info;
|
||||||
|
}.bind(this));
|
||||||
|
},
|
||||||
|
});
|
||||||
|
</script>
|
86
panels/zwave/zwave-network.html
Normal file
86
panels/zwave/zwave-network.html
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
<link rel="import" href="../../bower_components/polymer/polymer.html">
|
||||||
|
<link rel="import" href="../../bower_components/paper-card/paper-card.html">
|
||||||
|
<link rel="import" href="../../src/components/buttons/ha-call-service-button.html">
|
||||||
|
|
||||||
|
<dom-module id='zwave-network'>
|
||||||
|
<template>
|
||||||
|
<style include="iron-flex ha-style">
|
||||||
|
.content {
|
||||||
|
margin-top: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
paper-card {
|
||||||
|
display: block;
|
||||||
|
margin: 0 auto;
|
||||||
|
max-width: 600px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-actions.warning ha-call-service-button {
|
||||||
|
color: var(--google-red-500);
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<paper-card heading='Z-Wave Network Management'>
|
||||||
|
<div class='card-content'>
|
||||||
|
Z-Wave Network controls.
|
||||||
|
</div>
|
||||||
|
<div class='card-actions'>
|
||||||
|
<ha-call-service-button
|
||||||
|
hass='[[hass]]'
|
||||||
|
domain='zwave'
|
||||||
|
service='add_node_secure'
|
||||||
|
>Add Node</ha-call-service-button>
|
||||||
|
<ha-call-service-button
|
||||||
|
hass='[[hass]]'
|
||||||
|
domain='zwave'
|
||||||
|
service='remove_node'
|
||||||
|
>Remove Node</ha-call-service-button>
|
||||||
|
</div>
|
||||||
|
<div class='card-actions warning'>
|
||||||
|
<ha-call-service-button
|
||||||
|
hass='[[hass]]'
|
||||||
|
domain='zwave'
|
||||||
|
service='cancel_command'
|
||||||
|
>Cancel Command</ha-call-service-button>
|
||||||
|
</div>
|
||||||
|
<div class='card-actions'>
|
||||||
|
<ha-call-service-button
|
||||||
|
hass='[[hass]]'
|
||||||
|
domain='zwave'
|
||||||
|
service='heal_network'
|
||||||
|
>Heal Network</ha-call-service-button>
|
||||||
|
<ha-call-service-button
|
||||||
|
hass='[[hass]]'
|
||||||
|
domain='zwave'
|
||||||
|
service='start_network'
|
||||||
|
>Start Network</ha-call-service-button>
|
||||||
|
<ha-call-service-button
|
||||||
|
hass='[[hass]]'
|
||||||
|
domain='zwave'
|
||||||
|
service='stop_network'
|
||||||
|
>Stop Network</ha-call-service-button>
|
||||||
|
<ha-call-service-button
|
||||||
|
hass='[[hass]]'
|
||||||
|
domain='zwave'
|
||||||
|
service='soft_reset'
|
||||||
|
>Soft Reset</ha-call-service-button>
|
||||||
|
<ha-call-service-button
|
||||||
|
hass='[[hass]]'
|
||||||
|
domain='zwave'
|
||||||
|
service='test_network'
|
||||||
|
>Test Network</ha-call-service-button>
|
||||||
|
</div>
|
||||||
|
</paper-card>
|
||||||
|
</template>
|
||||||
|
</dom-module>
|
||||||
|
<script>
|
||||||
|
|
||||||
|
Polymer({
|
||||||
|
is: 'zwave-network',
|
||||||
|
|
||||||
|
properties: {
|
||||||
|
hass: {
|
||||||
|
type: Object,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
</script>
|
312
panels/zwave/zwave-node-config.html
Normal file
312
panels/zwave/zwave-node-config.html
Normal file
@ -0,0 +1,312 @@
|
|||||||
|
<link rel="import" href="../../bower_components/polymer/polymer.html">
|
||||||
|
<link rel="import" href="../../bower_components/paper-card/paper-card.html">
|
||||||
|
<link rel="import" href="../../bower_components/paper-dropdown-menu/paper-dropdown-menu.html">
|
||||||
|
<link rel='import' href='../../bower_components/paper-item/paper-item.html'>
|
||||||
|
<link rel='import' href="../../bower_components/paper-listbox/paper-listbox.html">
|
||||||
|
<link rel='import' href="../../bower_components/paper-input/paper-input.html">
|
||||||
|
|
||||||
|
<link rel="import" href="../../src/components/buttons/ha-call-service-button.html">
|
||||||
|
|
||||||
|
<dom-module id='zwave-node-config'>
|
||||||
|
<template>
|
||||||
|
<style include="iron-flex ha-style">
|
||||||
|
.content {
|
||||||
|
margin-top: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
paper-card {
|
||||||
|
display: block;
|
||||||
|
margin: 0 auto;
|
||||||
|
max-width: 600px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.device-picker {
|
||||||
|
@apply(--layout-horizontal);
|
||||||
|
@apply(--layout-center-center);
|
||||||
|
padding-left: 24px;
|
||||||
|
padding-right: 24px;
|
||||||
|
padding-bottom: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.help-text {
|
||||||
|
padding-left: 24px;
|
||||||
|
padding-right: 24px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<div class='content'>
|
||||||
|
<paper-card heading='Node config options'>
|
||||||
|
<template is='dom-if' if='[[wakeupNode]]'>
|
||||||
|
<div class='card-actions'>
|
||||||
|
<paper-input
|
||||||
|
float-label="Wakeup Interval"
|
||||||
|
type=number
|
||||||
|
value={{wakeupInput}}
|
||||||
|
placeholder=[[computeGetWakeupValue(selectedNode)]]>
|
||||||
|
<div suffix>seconds</div>
|
||||||
|
</paper-input>
|
||||||
|
<ha-call-service-button
|
||||||
|
hass='[[hass]]'
|
||||||
|
domain='zwave'
|
||||||
|
service='set_wakeup'
|
||||||
|
service-data='[[computeWakeupServiceData(wakeupInput)]]'
|
||||||
|
>Set Wakeup</ha-call-service-button>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<div class='device-picker'>
|
||||||
|
<paper-dropdown-menu label="Config parameter" class='flex'>
|
||||||
|
<paper-listbox
|
||||||
|
class="dropdown-content"
|
||||||
|
selected='{{selectedConfigParameter}}'>
|
||||||
|
<template is='dom-repeat' items='[[config]]' as='state'>
|
||||||
|
<paper-item>[[computeSelectCaptionConfigParameter(state)]]</paper-item>
|
||||||
|
</template>
|
||||||
|
</paper-listbox>
|
||||||
|
</paper-dropdown-menu>
|
||||||
|
</div>
|
||||||
|
<template is='dom-if' if="[[isConfigParameterSelected(selectedConfigParameter, 'List')]]">
|
||||||
|
<div class='device-picker'>
|
||||||
|
<paper-dropdown-menu label="Config value" class='flex' placeholder='{{loadedConfigValue}}'>
|
||||||
|
<paper-listbox
|
||||||
|
class="dropdown-content"
|
||||||
|
selected='{{selectedConfigValue}}'>
|
||||||
|
<template is='dom-repeat' items='[[selectedConfigParameterValues]]' as='state'>
|
||||||
|
<paper-item>[[state]]</paper-item>
|
||||||
|
</template>
|
||||||
|
</paper-listbox>
|
||||||
|
</paper-dropdown-menu>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<template is='dom-if' if="[[isConfigParameterSelected(selectedConfigParameter, 'Byte Short Int')]]">
|
||||||
|
<div class='card-actions'>
|
||||||
|
<paper-input
|
||||||
|
label='{{selectedConfigParameterNumValues}}'
|
||||||
|
type=number
|
||||||
|
value='{{selectedConfigValue}}'
|
||||||
|
max='{{configParameterMax}}'
|
||||||
|
min='{{configParameterMin}}'>
|
||||||
|
</paper-input>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<template is='dom-if' if="[[isConfigParameterSelected(selectedConfigParameter, 'Bool Button')]]">
|
||||||
|
<div class='device-picker'>
|
||||||
|
<paper-dropdown-menu label="Config value" class='flex' placeholder='{{loadedConfigValue}}'>
|
||||||
|
<paper-listbox
|
||||||
|
class="dropdown-content"
|
||||||
|
selected='{{selectedConfigValue}}'>
|
||||||
|
<template is='dom-repeat' items='[[selectedConfigParameterValues]]' as='state'>
|
||||||
|
<paper-item>[[state]]</paper-item>
|
||||||
|
</template>
|
||||||
|
</paper-listbox>
|
||||||
|
</paper-dropdown-menu>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<div class='help-text'>
|
||||||
|
<span>[[configValueHelpText]]</span>
|
||||||
|
</div>
|
||||||
|
<template is='dom-if' if="[[isConfigParameterSelected(selectedConfigParameter, 'Bool Button Byte Short Int List')]]">
|
||||||
|
<div class='card-actions'>
|
||||||
|
<ha-call-service-button
|
||||||
|
hass='[[hass]]'
|
||||||
|
domain='zwave'
|
||||||
|
service='set_config_parameter'
|
||||||
|
service-data=[[computeSetConfigParameterServiceData(selectedConfigValue)]]
|
||||||
|
>Set Config Parameter</ha-call-service-button>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</paper-card>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</dom-module>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
Polymer({
|
||||||
|
is: 'zwave-node-config',
|
||||||
|
|
||||||
|
properties: {
|
||||||
|
hass: {
|
||||||
|
type: Object,
|
||||||
|
},
|
||||||
|
|
||||||
|
nodes: {
|
||||||
|
type: Array,
|
||||||
|
observer: 'nodesChanged'
|
||||||
|
},
|
||||||
|
|
||||||
|
selectedNode: {
|
||||||
|
type: Number,
|
||||||
|
value: -1,
|
||||||
|
observer: 'nodesChanged'
|
||||||
|
},
|
||||||
|
|
||||||
|
config: {
|
||||||
|
type: Array,
|
||||||
|
value: function () {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
selectedConfigParameter: {
|
||||||
|
type: Number,
|
||||||
|
value: -1,
|
||||||
|
observer: 'selectedConfigParameterChanged'
|
||||||
|
},
|
||||||
|
|
||||||
|
configParameterMax: {
|
||||||
|
type: Number,
|
||||||
|
value: -1
|
||||||
|
},
|
||||||
|
|
||||||
|
configParameterMin: {
|
||||||
|
type: Number,
|
||||||
|
value: -1
|
||||||
|
},
|
||||||
|
|
||||||
|
configValueHelpText: {
|
||||||
|
type: String,
|
||||||
|
value: '',
|
||||||
|
computed: 'computeConfigValueHelp(selectedConfigParameter)'
|
||||||
|
},
|
||||||
|
|
||||||
|
selectedConfigParameterType: {
|
||||||
|
type: String,
|
||||||
|
value: ''
|
||||||
|
},
|
||||||
|
|
||||||
|
selectedConfigValue: {
|
||||||
|
type: Number,
|
||||||
|
value: -1,
|
||||||
|
observer: 'computeSetConfigParameterServiceData'
|
||||||
|
},
|
||||||
|
|
||||||
|
selectedConfigParameterValues: {
|
||||||
|
type: Array,
|
||||||
|
value: function () {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
selectedConfigParameterNumValues: {
|
||||||
|
type: String,
|
||||||
|
value: ''
|
||||||
|
},
|
||||||
|
|
||||||
|
loadedConfigValue: {
|
||||||
|
type: Number,
|
||||||
|
value: -1
|
||||||
|
},
|
||||||
|
|
||||||
|
wakeupInput: {
|
||||||
|
type: Number,
|
||||||
|
},
|
||||||
|
|
||||||
|
wakeupNode: {
|
||||||
|
type: Boolean,
|
||||||
|
value: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
listeners: {
|
||||||
|
'hass-service-called': 'serviceCalled',
|
||||||
|
},
|
||||||
|
|
||||||
|
serviceCalled: function (ev) {
|
||||||
|
if (ev.detail.success) {
|
||||||
|
var foo = this;
|
||||||
|
setTimeout(function () {
|
||||||
|
foo.refreshConfig(foo.selectedNode);
|
||||||
|
}, 5000);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
nodesChanged: function () {
|
||||||
|
if (!this.nodes) return;
|
||||||
|
this.wakeupNode = (this.nodes[this.selectedNode].attributes.wake_up_interval === 0 ||
|
||||||
|
this.nodes[this.selectedNode].attributes.wake_up_interval);
|
||||||
|
if (this.wakeupNode) {
|
||||||
|
if (this.nodes[this.selectedNode].attributes.wake_up_interval === 0) this.wakeupInput = '';
|
||||||
|
else this.wakeupInput = this.nodes[this.selectedNode].attributes.wake_up_interval;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
computeGetWakeupValue: function (selectedNode) {
|
||||||
|
if (this.selectedNode === -1 ||
|
||||||
|
!this.nodes[selectedNode].attributes.wake_up_interval) return 'unknown';
|
||||||
|
return (this.nodes[selectedNode].attributes.wake_up_interval);
|
||||||
|
},
|
||||||
|
|
||||||
|
computeWakeupServiceData: function (wakeupInput) {
|
||||||
|
return { node_id: this.nodes[this.selectedNode].attributes.node_id,
|
||||||
|
value: wakeupInput };
|
||||||
|
},
|
||||||
|
|
||||||
|
computeConfigValueHelp: function (selectedConfigParameter) {
|
||||||
|
if (selectedConfigParameter === -1) return '';
|
||||||
|
var helpText = this.config[selectedConfigParameter].value.help;
|
||||||
|
if (!helpText) return ['No helptext available'];
|
||||||
|
return helpText;
|
||||||
|
},
|
||||||
|
|
||||||
|
computeSetConfigParameterServiceData: function (selectedConfigValue) {
|
||||||
|
if (this.selectedNode === -1 || this.selectedConfigParameter === -1) return -1;
|
||||||
|
var valueData = null;
|
||||||
|
if (('Short Byte Int').includes(this.selectedConfigParameterType)) {
|
||||||
|
valueData = parseInt(selectedConfigValue, 10);
|
||||||
|
} if (('Bool Button').includes(this.selectedConfigParameterType)) {
|
||||||
|
valueData = this.selectedConfigParameterValues[selectedConfigValue];
|
||||||
|
} if (this.selectedConfigParameterType === 'List') {
|
||||||
|
valueData = this.selectedConfigParameterValues[selectedConfigValue];
|
||||||
|
}
|
||||||
|
return { node_id: this.nodes[this.selectedNode].attributes.node_id,
|
||||||
|
parameter: this.config[this.selectedConfigParameter].key,
|
||||||
|
value: valueData };
|
||||||
|
},
|
||||||
|
|
||||||
|
selectedConfigParameterChanged: function (selectedConfigParameter) {
|
||||||
|
if (selectedConfigParameter === -1) return;
|
||||||
|
this.selectedConfigValue = -1;
|
||||||
|
this.loadedConfigValue = -1;
|
||||||
|
this.selectedConfigParameterValues = [];
|
||||||
|
this.selectedConfigParameterType = this.config[selectedConfigParameter].value.type;
|
||||||
|
this.configParameterMax = this.config[selectedConfigParameter].value.max;
|
||||||
|
this.configParameterMin = this.config[selectedConfigParameter].value.min;
|
||||||
|
this.loadedConfigValue = this.config[selectedConfigParameter].value.data;
|
||||||
|
this.configValueHelpText = this.config[selectedConfigParameter].value.help;
|
||||||
|
if (('Short Byte Int').includes(this.selectedConfigParameterType)) {
|
||||||
|
this.selectedConfigParameterNumValues = this.config[selectedConfigParameter].value.data_items;
|
||||||
|
this.selectedConfigValue = this.loadedConfigValue;
|
||||||
|
}
|
||||||
|
if (('Bool Button').includes(this.selectedConfigParameterType)) {
|
||||||
|
this.selectedConfigParameterValues = ['True', 'False'];
|
||||||
|
if (this.config[selectedConfigParameter].value.data) {
|
||||||
|
this.loadedConfigValue = 'True';
|
||||||
|
} else this.loadedConfigValue = 'False';
|
||||||
|
}
|
||||||
|
if (('List').includes(this.selectedConfigParameterType)) {
|
||||||
|
this.selectedConfigParameterValues = this.config[selectedConfigParameter].value.data_items;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
isConfigParameterSelected: function (selectedConfigParameter, type) {
|
||||||
|
if (selectedConfigParameter === -1) return false;
|
||||||
|
if (this.config[selectedConfigParameter].value.type === type) return true;
|
||||||
|
if (type.includes(this.config[selectedConfigParameter].value.type)) return true;
|
||||||
|
return false;
|
||||||
|
},
|
||||||
|
|
||||||
|
computeSelectCaptionConfigParameter: function (stateObj) {
|
||||||
|
return (stateObj.key + ': ' + stateObj.value.label);
|
||||||
|
},
|
||||||
|
|
||||||
|
refreshConfig: function (selectedNode) {
|
||||||
|
var configData = [];
|
||||||
|
this.hass.callApi('GET', 'zwave/config/' + this.nodes[selectedNode].attributes.node_id).then(function (config) {
|
||||||
|
Object.entries(config).forEach(([key, value]) => {
|
||||||
|
configData.push({ key, value });
|
||||||
|
});
|
||||||
|
this.config = configData;
|
||||||
|
this.selectedConfigParameterChanged(this.selectedConfigParameter);
|
||||||
|
}.bind(this));
|
||||||
|
},
|
||||||
|
});
|
||||||
|
</script>
|
81
panels/zwave/zwave-node-information.html
Normal file
81
panels/zwave/zwave-node-information.html
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
<link rel="import" href="../../bower_components/polymer/polymer.html">
|
||||||
|
<link rel="import" href="../../bower_components/paper-card/paper-card.html">
|
||||||
|
|
||||||
|
<dom-module id='zwave-node-information'>
|
||||||
|
<template>
|
||||||
|
<style include="iron-flex ha-style">
|
||||||
|
.content {
|
||||||
|
margin-top: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.node-info {
|
||||||
|
margin-left: 16px;
|
||||||
|
text-transform: capitalize;
|
||||||
|
}
|
||||||
|
|
||||||
|
paper-card {
|
||||||
|
display: block;
|
||||||
|
margin: 0 auto;
|
||||||
|
max-width: 600px;
|
||||||
|
}
|
||||||
|
|
||||||
|
paper-button[toggles][active] {
|
||||||
|
background: lightgray;
|
||||||
|
}
|
||||||
|
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<div class='content'>
|
||||||
|
<paper-card heading='Node Information'>
|
||||||
|
<div class='card-actions'>
|
||||||
|
<paper-button toggles raised noink active={{nodeInfoActive}}>Show</paper-button>
|
||||||
|
</div>
|
||||||
|
<template is='dom-if' if={{nodeInfoActive}}>
|
||||||
|
<template is='dom-repeat' items='[[selectedNodeAttrs]]' as='state'>
|
||||||
|
<div class='node-info'>
|
||||||
|
<span>[[state]]</span>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</template>
|
||||||
|
</paper-card>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</template>
|
||||||
|
</dom-module>
|
||||||
|
<script>
|
||||||
|
|
||||||
|
Polymer({
|
||||||
|
is: 'zwave-node-information',
|
||||||
|
|
||||||
|
properties: {
|
||||||
|
nodes: {
|
||||||
|
type: Array,
|
||||||
|
observer: 'nodeChanged'
|
||||||
|
},
|
||||||
|
|
||||||
|
selectedNode: {
|
||||||
|
type: Number,
|
||||||
|
value: -1,
|
||||||
|
observer: 'nodeChanged'
|
||||||
|
},
|
||||||
|
|
||||||
|
selectedNodeAttrs: {
|
||||||
|
type: Array,
|
||||||
|
},
|
||||||
|
|
||||||
|
nodeInfoActive: {
|
||||||
|
type: Boolean,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
nodeChanged: function (selectedNode) {
|
||||||
|
if (!this.nodes || selectedNode === -1) return;
|
||||||
|
var nodeAttrs = this.nodes[this.selectedNode].attributes;
|
||||||
|
var att = [];
|
||||||
|
Object.entries(nodeAttrs).forEach(([key, value]) => {
|
||||||
|
att.push(key + ': ' + value);
|
||||||
|
});
|
||||||
|
this.selectedNodeAttrs = att.sort();
|
||||||
|
},
|
||||||
|
});
|
||||||
|
</script>
|
171
panels/zwave/zwave-usercodes.html
Normal file
171
panels/zwave/zwave-usercodes.html
Normal file
@ -0,0 +1,171 @@
|
|||||||
|
<link rel="import" href="../../bower_components/polymer/polymer.html">
|
||||||
|
<link rel="import" href="../../bower_components/paper-card/paper-card.html">
|
||||||
|
<link rel="import" href="../../bower_components/paper-dropdown-menu/paper-dropdown-menu.html">
|
||||||
|
<link rel='import' href='../../bower_components/paper-item/paper-item.html'>
|
||||||
|
<link rel='import' href="../../bower_components/paper-listbox/paper-listbox.html">
|
||||||
|
<link rel='import' href="../../bower_components/paper-input/paper-input.html">
|
||||||
|
|
||||||
|
<link rel="import" href="../../src/components/buttons/ha-call-service-button.html">
|
||||||
|
|
||||||
|
<dom-module id='zwave-usercodes'>
|
||||||
|
<template>
|
||||||
|
<style include="iron-flex ha-style">
|
||||||
|
.content {
|
||||||
|
margin-top: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
paper-card {
|
||||||
|
display: block;
|
||||||
|
margin: 0 auto;
|
||||||
|
max-width: 600px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.device-picker {
|
||||||
|
@apply(--layout-horizontal);
|
||||||
|
@apply(--layout-center-center);
|
||||||
|
padding-left: 24px;
|
||||||
|
padding-right: 24px;
|
||||||
|
padding-bottom: 24px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<div class='content'>
|
||||||
|
<paper-card heading='Node user codes'>
|
||||||
|
<div class='device-picker'>
|
||||||
|
<paper-dropdown-menu label="Code slot" class='flex'>
|
||||||
|
<paper-listbox
|
||||||
|
class="dropdown-content"
|
||||||
|
selected='{{selectedUserCode}}'>
|
||||||
|
<template is='dom-repeat' items='[[userCodes]]' as='state'>
|
||||||
|
<paper-item>[[computeSelectCaptionUserCodes(state)]]</paper-item>
|
||||||
|
</template>
|
||||||
|
</paper-listbox>
|
||||||
|
</paper-dropdown-menu>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<template is='dom-if' if="[[isUserCodeSelected(selectedUserCode)]]">
|
||||||
|
<div class='card-actions'>
|
||||||
|
<paper-input
|
||||||
|
label='User code'
|
||||||
|
type=number
|
||||||
|
value='{{selectedUserCodeValue}}'
|
||||||
|
maxlength='{{userCodeMaxLen}}'
|
||||||
|
min='0'>
|
||||||
|
</paper-input>
|
||||||
|
</div>
|
||||||
|
<div class='card-actions'>
|
||||||
|
<ha-call-service-button
|
||||||
|
hass='[[hass]]'
|
||||||
|
domain='lock'
|
||||||
|
service='set_usercode'
|
||||||
|
service-data='[[computeUserCodeServiceData(selectedUserCodeValue, "Add")]]'
|
||||||
|
>Set Usercode</ha-call-service-button>
|
||||||
|
<ha-call-service-button
|
||||||
|
hass='[[hass]]'
|
||||||
|
domain='lock'
|
||||||
|
service='clear_usercode'
|
||||||
|
service-data='[[computeUserCodeServiceData(selectedUserCode, "Delete")]]'
|
||||||
|
>Delete Usercode</ha-call-service-button>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</paper-card>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</dom-module>
|
||||||
|
<script>
|
||||||
|
|
||||||
|
Polymer({
|
||||||
|
is: 'zwave-usercodes',
|
||||||
|
|
||||||
|
properties: {
|
||||||
|
hass: {
|
||||||
|
type: Object,
|
||||||
|
},
|
||||||
|
|
||||||
|
nodes: {
|
||||||
|
type: Array,
|
||||||
|
},
|
||||||
|
|
||||||
|
selectedNode: {
|
||||||
|
type: Number,
|
||||||
|
},
|
||||||
|
|
||||||
|
userCodes: {
|
||||||
|
type: Object,
|
||||||
|
},
|
||||||
|
|
||||||
|
userCodeMaxLen: {
|
||||||
|
type: Number,
|
||||||
|
value: 4
|
||||||
|
},
|
||||||
|
|
||||||
|
selectedUserCode: {
|
||||||
|
type: Number,
|
||||||
|
value: -1,
|
||||||
|
observer: 'selectedUserCodeChanged'
|
||||||
|
},
|
||||||
|
|
||||||
|
selectedUserCodeValue: {
|
||||||
|
type: Number,
|
||||||
|
value: -1
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
listeners: {
|
||||||
|
'hass-service-called': 'serviceCalled',
|
||||||
|
},
|
||||||
|
serviceCalled: function (ev) {
|
||||||
|
if (ev.detail.success) {
|
||||||
|
var foo = this;
|
||||||
|
setTimeout(function () {
|
||||||
|
foo.refreshUserCodes(foo.selectedNode);
|
||||||
|
}, 5000);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
isUserCodeSelected: function (selectedUserCode) {
|
||||||
|
if (selectedUserCode === -1) return false;
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
|
||||||
|
computeSelectCaptionUserCodes: function (stateObj) {
|
||||||
|
return (stateObj.key + ': ' + stateObj.value.label);
|
||||||
|
},
|
||||||
|
|
||||||
|
selectedUserCodeChanged: function (selectedUserCode) {
|
||||||
|
if (this.selectedUserCode === -1 || selectedUserCode === -1) return;
|
||||||
|
var value = (parseInt((this.userCodes[selectedUserCode].value.code).trim()));
|
||||||
|
this.userCodeMaxLen = (this.userCodes[selectedUserCode].value.length);
|
||||||
|
if (isNaN(value)) this.selectedUserCodeValue = '';
|
||||||
|
else this.selectedUserCodeValue = value;
|
||||||
|
},
|
||||||
|
|
||||||
|
computeUserCodeServiceData: function (selectedUserCodeValue, type) {
|
||||||
|
if (this.selectedNode === -1 || !selectedUserCodeValue) return -1;
|
||||||
|
var serviceData = null;
|
||||||
|
var valueData = null;
|
||||||
|
if (type === 'Add') {
|
||||||
|
valueData = selectedUserCodeValue;
|
||||||
|
serviceData = { node_id: this.nodes[this.selectedNode].attributes.node_id,
|
||||||
|
code_slot: this.selectedUserCode,
|
||||||
|
usercode: valueData };
|
||||||
|
}
|
||||||
|
if (type === 'Delete') {
|
||||||
|
serviceData = { node_id: this.nodes[this.selectedNode].attributes.node_id,
|
||||||
|
code_slot: this.selectedUserCode };
|
||||||
|
}
|
||||||
|
return serviceData;
|
||||||
|
},
|
||||||
|
|
||||||
|
refreshUserCodes: function (selectedNode) {
|
||||||
|
this.selectedUserCodeValue = '';
|
||||||
|
var userCodes = [];
|
||||||
|
this.hass.callApi('GET', 'zwave/usercodes/' + this.nodes[selectedNode].attributes.node_id).then(function (usercodes) {
|
||||||
|
Object.entries(usercodes).forEach(([key, value]) => {
|
||||||
|
userCodes.push({ key, value });
|
||||||
|
});
|
||||||
|
this.userCodes = userCodes;
|
||||||
|
this.selectedUserCodeChanged(this.selectedUserCode);
|
||||||
|
}.bind(this));
|
||||||
|
},
|
||||||
|
});
|
||||||
|
</script>
|
Loading…
x
Reference in New Issue
Block a user